Страницы

Поиск по вопросам

четверг, 11 октября 2018 г.

Десятичные дроби типа double в java [дубликат]

На данный вопрос уже ответили: Вычисления на числах с плавающей точкой не работают 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, а правая нет.

Комментариев нет:

Отправить комментарий