На данный вопрос уже ответили:
Вычисления на числах с плавающей точкой не работают
2 ответа
Есть код:
public class Drob {
public static void main(String[] args) {
double x = 0.1;
System.out.println(x+x);
System.out.println(x+x+x); // Три раза прибавили X
System.out.println(x+x+x+x+x); // Пять раз прибавили X
System.out.println(x+x+x+x+x+x+x+x+x+x); //Десять раз прибавили X
}
}
На выходе он даёт это:
0.2
0.30000000000000004
0.5
0.9999999999999999
Против первого и третьего ответа у меня возражений нет. Но откуда на хвосте 4*(10^-17) во втором ответе? И как это соотносится с -1*(10^-16) в четвертом ответе?
Ответ
Давайте зайдём с другой стороны. По стандарту IEEE 754*, число типа double хранится в виде ± n × 2k. Это значит, что при записи
double d = 0.1;
число в переменной d вовсе не будет равно 0.1, потому что 0.1 не представимо в указанном виде. Ясно, почему?** Вместо этого в d будет записано какое-то приближение к 0.1
Поэтому и d + d + (10 раз) + d не будет в точности равно 1.
Дополнительное чтение по теме: OMG Ponies!!!
*По стандарту языка, числа с плавающей запятой соответствуют стандарту IEEE 754. (И не только в Java, кстати.)
**Потому что все числа упомянутого в стандарте IEEE 754 вида представляются в виде натуральной дроби, знаменатель которой есть степень двойки, а 1/10 таким числом не является. Действительно, если m/2n = 1/10, то 10 × m = 2n, и левая часть делится на 5, а правая нет.
Комментариев нет:
Отправить комментарий