Пакетная операция возвращает "Ошибка деления на ноль" с отложенным расширением и допустимой операцией
Следующая строка кода выполняется через мой текущий проект:
set /a "hp = hp - ((atk*arandom)/((edef*6)/edefbonus))"
А вот как это выглядит, когда вы заменяете переменные их значениями:
set /a "hp = 50 - ((2*2)/((1*6)/8))"
Ответ на это - 44.666667, который должен быть округлен до 45. Но вместо этого Пакет просто говорит мне "Делить на ноль ошибок", когда код выполняется, как с версией, которая использует переменные, так и с версией, которая вместо этого использует числа.
Я действительно потерян для подсказок. Я проверил наличие неравных скобок, я проверил наличие неустановленных переменных и установлен EnabledDelayedExpansion. Так что я делаю не так...?
3 ответа
Если нет причины делить знаменатель на edfbonus вместо умножения на него числителя, вы можете избежать проблемы делителя нуля, переставив вычисления:
set /a "hp = hp - ((atk*arandom*edefbonus)/(edef*6))"
Внешние скобки и кавычки не нужны, и set /a имеет оператор, который сохраняет некоторые операции ввода и убирает выражения вроде этого:
set /a hp -= atk*arandom*edefbonus/(edef*6)
Поскольку вы упомянули округление, я добавлю это:
Предоставлено значение справа от -=
Оператор выше всегда положителен, самый простой способ сделать округление:
set /a hp -= (10*atk*arandom*edefbonus/(edef*6)+5)/10
Обратите внимание, что мы умножаем на 10 до деления, а не после него, поэтому вычисление идет так:
10*2*2*8 =320
1*6 =6
320/6 =53
53+5 =58
58/10 =5
Если мы умножим на 10 после деления, как в
set /a hp -= (atk*arandom*edefbonus/(edef*6)*10+5)/10
,
расчет будет идти:
2*2*8 =32
1*6 =6
32/6 =5 (we just lost the fraction digit, so rounding won't work)
5*10 =50
50+5 =55
55/10 =5
Тот же результат, но только потому, что округление все равно было бы округлено вниз.
Пакет не может обрабатывать числа с плавающей запятой, только целые числа.
Так ((1*6)/8)
знак равно 0
вместо 0.75
, Вы тогда пытаетесь разделить (2*2)
тем 0
, давая вам ошибку "Делить на ноль".
Предлагаемое решение? Вместо этого используйте PowerShell:
PS Y:\> $hp = 50 - ((2*2)/((1*6)/8))
PS Y:\> $hp
44.6666666666667
Связанный вопрос SU:
Связанный ТАК вопрос:
Пакетная операция возвращает "Ошибка деления на ноль"
set /a "hp = 50 - ((2*2)/((1*6)/8))"
Это потому что 1*6
знак равно 6
а также 6/8
знак равно 0.75
,
А также:
Любое вычисление SET /A, которое возвращает дробный результат, будет округлено до ближайшего целого числа.
Так 0.75
округляется до 0
,
6/0
возвращает "Ошибка деления на ноль".
обходные
Не существует реальных обходных путей, позволяющих использовать математику с плавающей запятой, кроме использования других языков сценариев.
Единственным исключением может быть, если у вас ограниченное и фиксированное количество десятичных знаков (например, 2), тогда вы можете просто умножить все на 100.
Чтобы отобразить десятичный разделитель в конечных результатах, объедините целочисленное деление на 100, затем десятичный разделитель и деление по модулю на 100:
SET Whole = Result / 100 SET "Fraction = Result %% 100" SET Result=%Whole%.%Fraction%
Это может нарушить 32-битный лимит.
В целом, для математики с плавающей запятой я бы рекомендовал использовать другие языки сценариев.
Исходный Math в пакетных файлах NT
Арифметические выражения (SET /a)
Поместить выражения в "кавычки" необязательно для простой арифметики, но необходимо для любого выражения, использующего логические операторы.
Любое вычисление SET /A, которое возвращает дробный результат, будет округлено до ближайшего целого числа.
Исходный набор
Дальнейшее чтение
- Индекс AZ командной строки Windows CMD - Отличный справочник по всем вопросам, связанным с командной строкой Windows.
- set - отображать, устанавливать или удалять переменные окружения CMD. Изменения, сделанные с помощью SET, будут сохраняться только в течение текущего сеанса CMD.