Как мне установить точность арифметической операции SET на делениях?
например. SET /A t=3/4
Но это дает результат как ' 0
', а не ' 0.75
' (я хочу по крайней мере 2 десятичных знака)
Или есть какой-либо другой метод для таких арифметических операций (использующий кроме " set /A
"), чтобы произойти в пакетных файлах?
SET /A
работает только на целых числах. Таким образом, нет никакого способа0.75
использовать этоОтветы:
Если вы используете Microsoft
CMD
, то то, что сказал Nifle, применимо. Однако, если вы используете для его замены TCC / LE от JP Software , существует не только другой способ выполнения арифметики в командных сценариях, но он не ограничивается целочисленной арифметикой, а точность вычислений контролируется.Конечно, TCC / LE поддерживает
/A
опцию дляSET
команды. Но, как говорится в документации, можно также выполнять арифметику с@EVAL[]
функцией переменной :Точность вывода в
%@EVAL[]
расчете является управляемой опцией, которая устанавливается тремя способами:OPTION
командой/F
возможностьюSETDOS
команды%@EVAL[]
функцииисточник
SET / A работает только на целых числах. Таким образом, нет никакого способа получить 0,75, используя это.
И я не знаю другого способа сделать арифметику в пакетных файлах.
источник
CMD
. «Вы не можете делать то, что хотите, с командным интерпретатором, который у вас есть». является действительным ответом.Возможно, вы не сможете делать то, что хотите, но вы можете приблизить желаемый результат, умножив и разделив на степени 10 и выполнив манипуляции со строками. Например, рассмотрим это
divide.bat
:%variable_name:~start_pos,length%
является обозначением подстроки переменной командной строки. Отрицательные числа относятся к длине строки (значение переменной); отсутствующая длина означает остаток строки.Вот некоторые примеры результатов:
В последнем примере ( ваш пример) на
q
самом деле 750. Если вы хотите вычислить 75% чего-либо, либо%q%
и разделить на 1000, или%q%
и помните, что результат равен 1000-кратному его истинному значению, и вам нужно использовать обозначение подстроки при его отображении.источник
Отсутствие начальных нулей в результате присваивания set / a приводит к сбою деления, когда результат меньше .100; остроумие,
разделить 3 40 -> д = 0,75
Добавление начальных нулей перед извлечением последних 3 цифр устраняет эту проблему, по крайней мере, для положительных чисел.
Вот решение (только для положительных чисел):
Другая проблема - отрицательные числа. Следующим последним символом может быть знак «-», который не должен появляться в дробной части. Самое простое решение для этого - удалить знак (если есть) и затем отобразить его перед десятичной строкой:
Наконец, есть проблема округления. Если вы довольны значением, усеченным до последнего отображаемого десятичного знака, все готово. Если вы хотите, чтобы отображаемое значение было точным в пределах его точности, требуется округление. Поскольку мы уже собираемся работать с абсолютным значением (убрав знак), округление упрощено. Нам не нужно округлять положительные и отрицательные числа противоположно:
Это последнее деление на 10 можно устранить, извлекая другой набор цифр для отображения:
Умножение на 10000 уменьшает область (т. Е. Диапазон параметра) функции. 32-битная арифметика cmd.exe может представлять значения от - (2 ^ 31) до (2 ^ 31) -1. Это от {-2147483648 до +2147483647}. Предварительное масштабирование на 10000 уменьшает это значение от {-214748 до +214748}.
Для обработки больших значений числителя можно выполнить деление без предварительного масштабирования, а затем масштабировать результат, используя модуль для вычисления дробной части.
Следующий код в основном извлечен из одного из моих проектов. Я переименовал переменные для общности и добавил код, чтобы разрешить отрицательные значения знаменателя. В моем проекте я хотел, чтобы отображаемое значение показывало ноль для числа единиц, а не начиналось с десятичной точки для значений меньше 1, поэтому я сгенерировал часть единиц арифметически, а не с использованием подстроки.
В случае, если вы предпочитаете не нулевую единицу для коэффициентов меньше единицы, я включил
if defined no_zero_unit
условие, чтобы выбрать, какой формат отображать для небольших коэффициентов.Этот код не защищен от переполнения. Хотя он может обрабатывать значения числителя или знаменателя до +/- 2147483647, он не может обрабатывать оба одновременно. Как отмечено в комментариях, переполнение может произойти, если min (abs (% 1), abs (% 2) -1) больше, чем 214748, или если abs (частное) больше, чем 214748.3642.
Если вы попытаетесь разделить -2147483648 на -1 (что невозможно в 32-разрядной арифметике со знаком), то при вычислении модуля он вылетит из cmd.exe с целочисленным переполнением. Кажется, хотя cmd.exe правильно обрабатывает исключение для деления, те же самые операнды искажают его для модуля.
Я не включал тесты для этих условий переполнения, хотя было бы довольно просто добавить их. Фактически мы могли бы удвоить диапазон отношения с помощью деления без знака для деления на 10. Сдвиг десятичной строки вправо не сработает, поскольку переполнение уже произошло. Если это решит проблему для кого-то, я буду рад выложить решение. Это добавляет только одну строку кода.
ПРИМЕЧАНИЕ: задержка расширения должна быть включена. Если вы удалите
if defined no_zero_units ... else ...
условное выражение и включите только код нужного вам формата (без скобок), вам не понадобится задержка с расширением.Вот:
Чтобы устранить ограничение на частное, мы не можем просто поместить целую и дробную части в одну и ту же переменную. Единственная причина сделать это, когда остаток используется для вычисления дроби, состоит в том, что перенос от округления будет автоматически распространяться из дроби в целочисленную часть.
Для устранения ограничений на Числитель и Знаменатель требуются средства вычисления rem * 10000 / den без возможности переполнения при умножении.
Масштабирование как rem, так и den с помощью одного и того же фактора обеспечивает это за счет некоторой точности. Однако потеря точности имеет вычисляемую верхнюю границу и не имеет значения, когда предполагаемая конечная точность составляет 3 десятичных знака. Так как ОП попросил только «по крайней мере 2», это должно получиться хорошо.
Используемый здесь подход заключается в проверке rem по максимально допустимому значению и смещении вправо и rem и den до тех пор, пока rem не превысит этот предел. Как поясняется в комментариях, максимальная ошибка, возникающая в результате этого, появится в 5-м десятичном знаке.
Расширить этот алгоритм до 4 отображаемых десятичных цифр с округлением было бы нереально. Множитель становится равным 100000, поэтому максимальное значение остатка после масштабирования уменьшается в 10 раз. Таким образом, точность вычисления ухудшается в 10 раз, в то время как отображаемая точность увеличивается на тот же коэффициент, и теперь эти два значения встречаются в последний раз. отображаемая цифра. Даже использование арифметики без знака для деления на 10 при округлении только улучшит это в 2 раза - недостаточно для корректировки результата. Однако если бы округление не применялось, множитель все равно был бы равен 10000, а точность была бы такой же, как в этой версии, но не округлялась.
источник