Как Вы имеете дело со странным поведением Java с оператором модуля, когда использование удваивается?
Например, Вы ожидали бы результат 3.9 - (3.9 % 0.1)
быть 3.9
(и действительно, Google говорит, что я не схожу с ума), но когда я выполняю его в Java, я добираюсь 3.8000000000000003
.
Я понимаю, что это - результат того, как хранилища Java и процессы удваиваются, но являются там способом работать вокруг этого?
Используйте точный тип, если вам нужен точный результат:
double val = 3.9 - (3.9 % 0.1);
System.out.println(val); // 3.8000000000000003
BigDecimal x = new BigDecimal( "3.9" );
BigDecimal bdVal = x.subtract( x.remainder( new BigDecimal( "0.1" ) ) );
System.out.println(bdVal); // 3.9
Почему 3.8000...003? Потому что Java использует FPU для вычисления результата. 3.9 невозможно сохранить точно в IEEE двойной точности нотации, поэтому он хранит 3.89999... вместо. А 3,8999%0,01 дает 0,09999... следовательно, результат немного больше, чем 3,8.
Вы можете использовать java.math.BigDecimal и его метод divideAndRemainder().
Если вы знаете количество десятичных знаков, с которыми имеете дело, вы можете сначала попытаться преобразовать их в целые числа. Это просто классический случай неточности с плавающей запятой. Вместо 3.9% 0.1
вы делаете что-то вроде 3.899% 0.0999
Результат числа с плавающей запятой операция остатка, вычисленная Оператор% отличается от этого произведенный остальной операцией определено IEEE 754. IEEE 754 операция остатка вычисляет остаток от округления, не усекающее деление, и поэтому его поведение не аналогично поведению обычный оператор целочисленного остатка. Вместо этого язык программирования Java определяет% для операций с плавающей запятой вести себя аналогично что из целочисленного остатка оператор; это можно сравнить с библиотечная функция C fmod. IEEE 754 операция остатка может быть вычисляется библиотечной подпрограммой Math.IEEE Остаток.
Другими словами, это связано с тем, что Java округляет результат деления, участвующего в вычислении остатка, в то время как IEEE754 определяет усечение ответа деления. Этот конкретный случай, кажется, очень ясно показывает эту разницу.
Вы можете получить ожидаемый ответ, используя Math.IEEEremainder:
System.out.println(3.9 - (3.9 % 0.1));
System.out.println(3.9 - Math.IEEEremainder(3.9, 0.1));