Как использовать модуль для float/double?

Я создаю калькулятор RPN для школьного проекта. У меня проблемы с оператором модуля. Поскольку мы используем тип данных double, модуль не будет работать с числами с плавающей запятой. Например, 0,5% 0,3 должно возвращать 0,2, но я получаю исключение деления на ноль.

В инструкции сказано использовать fmod(). Я везде искал fmod(), включая javadocs, но не могу найти. Я начинаю думать, что это метод, который мне придется создать?

редактировать: хм, странно. Я только что снова ввел эти цифры, и, похоже, все работает нормально... но на всякий случай. Нужно ли мне следить за использованием оператора мода в Java при использовании плавающих типов? Я знаю, что что-то подобное невозможно сделать на С++ (я думаю).


person ShrimpCrackers    schedule 01.06.2010    source источник


Ответы (4)


Вероятно, у вас была опечатка при первом запуске.

оценка 0.5 % 0.3 возвращает «0,2» (двойной), как и ожидалось.

У Mindprod есть хороший обзор работы модуля в Java.

person RodeoClown    schedule 01.06.2010
comment
но 1.0 % 0.1 возвращает ... 0.09999999999999995 в результате ошибки округления. Любая идея, как исправить это (предположительно, со значениями эпсилон?) - person Groostav; 18.11.2015
comment
ошибки округления всегда будут возникать при вычислениях с плавающей запятой. Либо примите значение, как оно задано, либо округлите его до ближайшего необходимого значения. - person Anarchofascist; 22.01.2016
comment
String.format("%.8f",1.0%0.1) возвращает 0.10000000 - person Anarchofascist; 22.01.2016
comment
@Groostav Это не ошибка округления. 0.1 не может быть представлен как двойное значение, поэтому результатом является ближайшее представимое двойное значение. - person augurar; 23.01.2017
comment
Это хуже, чем просто округление результата. Вы сказали 1.0 % 0.1, но на самом деле вы сделали 1.0 % 0.10000000000000000555111512..., поэтому, если вы увеличите это 1,0, ответ будет все дальше и дальше от 0,1. - person Mark Jeronimus; 16.06.2017
comment
Ссылка, которую вы указали, предназначена для IEEEremainder, и она работает иначе, чем %, вы можете проверить с помощью -5.1 % 3 и Math.IEEEremainder (-5.1, 3) - person A. Mashreghi; 11.10.2019

В отличие от C, Java позволяет использовать % как для целых чисел, так и для чисел с плавающей запятой, и (в отличие от C89 и C++) он четко определен для всех входных данных (включая отрицательные значения):

Из JLS §15.17.3:

Результат операции остатка с плавающей запятой определяется правилами арифметики IEEE:

  • Если любой из операндов равен NaN, результатом будет NaN.
  • Если результат не NaN, знак результата равен знаку делимого.
  • Если делимое равно бесконечности, или делитель равен нулю, или и то, и другое, результатом будет NaN.
  • Если делимое конечно, а делитель равен бесконечности, результат равен делимому.
  • Если делимое равно нулю, а делитель конечен, результат равен делимому.
  • В остальных случаях, когда не задействованы ни бесконечность, ни ноль, ни NaN, остаток с плавающей запятой r от деления делимого n на делитель d определяется математическим соотношением r=n-(d·q ), где q — целое число, отрицательное, только если n/d отрицательное, и положительное, только если n/d положительное, и чья величина настолько велика, насколько это возможно, но не превышает величины истинного математического отношения n и d.

Итак, для вашего примера 0,5/0,3 = 1,6... . q имеет тот же знак (положительный), что и 0,5 (делимое), а величина равна 1 (целое число с наибольшей величиной, не превышающей величину 1,6...), и r = 0,5 - (0,3 * 1) = 0,2

person Matthew Flaschen    schedule 01.06.2010
comment
Последний пункт — стена текста. Было бы понятнее сказать, что на примере: 0.5 % 0.3 = 0.2 и (-0.5) % 0.3 = -0.2 - person CoffeDeveloper; 01.08.2015

Я думал, что обычный оператор модуля будет работать для этого в java, но его нетрудно закодировать. Просто разделите числитель на знаменатель и возьмите целую часть результата. Умножьте это на знаменатель и вычтите результат из числителя.

x = n / d
xint = Integer portion of x
result = n - d * xint
person WhirlWind    schedule 01.06.2010
comment
имеет смысл в логике, но неприменим к реальной реализации - person Valen; 03.03.2019
comment
@Valen: В частности, он округляется, тогда как большинство реальных операций с остатком (включая % и IEEEremainder в Java) являются точными. - person Davis Herring; 05.03.2019

fmod — стандартная функция C для обработки модуля с плавающей запятой; Я предполагаю, что ваш источник говорил, что Java обрабатывает модуль с плавающей запятой так же, как функция C fmod. В Java вы можете использовать оператор % для удвоения так же, как и для целых чисел:

int x = 5 % 3; // x = 2
double y = .5 % .3; // y = .2
person Michael Mrozek    schedule 01.06.2010