System.out.println(2.14656);
2.14656
System.out.println(2.14656%2);
0.14656000000000002
ВТФ?
System.out.println(2.14656);
2.14656
System.out.println(2.14656%2);
0.14656000000000002
ВТФ?
Дают ожидаемые результаты. Ваши ожидания неверны.
Когда вы вводите литерал двойной точности 2.14656
, вы фактически получаете ближайшее значение двойной точности, а именно:
2.14656000000000002359001882723532617092132568359375
println
округляет это значение при выводе (до 17 значащих цифр), поэтому вы видите ожидаемое значение.
После операции модуля (что является точным) значение равно:
0.14656000000000002359001882723532617092132568359375
Опять же, это округляется при печати, но поскольку на одну первую цифру меньше, точка округления находится на одну цифру дальше вправо, и поэтому вы видите этот замыкающий 2
.
Система с основанием 2 используется для хранения числа с основанием 10 произвольной точности.
При использовании целочисленного двоичного числа «круглые» числа — это 2, 4, 8, 16, 32, 64 и т. д. Вы заметите, что ни одно из них не является 10, 100, 1000, 10000 или чем-то еще, что можно было бы считать « круглое" число в базе-10.
Значения с плавающей запятой и двойные значения были созданы для быстрых операций внутри ЦП. Вычислить между несколькими числами можно быстро, даже если вы делите 1,42E-13 на 2,11E47. Они не были созданы для получения «круглых» чисел по основанию 10. Это побочный эффект этого решения.
При использовании чисел с плавающей запятой вы должны признать, что это произойдет. Это не 100% точность, но в остальном она верна. Поэтому вам никогда не следует использовать переменные с плавающей запятой там, где вам нужна 100% точность. Там, где вам нужно это сделать, найдите способ сохранить его в значении int. Это также хорошая идея, когда вы используете число с плавающей запятой, чтобы округлить вывод до числа десятичных знаков, чтобы избежать случайного отображения, как у вас там.
Например, я работаю в финансовой сфере, и мы представляем рыночные цены в виде количества тиков, а не фактической цены. Когда нам нужно отобразить цену, мы умножаем это значение на размер тика, 1/100, 1/32 или 1/20 и т. д., а затем округляем до соответствующего количества знаков после запятой. Количество тиков, числитель и знаменатель размера тика хранятся в наших базах данных как целые числа. На самом деле мы не храним значения с плавающей запятой ни для чего, кроме вычисляемых значений, таких как скользящие средние.
http://en.wikipedia.org/wiki/Round-off_error#Representation_error