Почему Visual Studio 2008 сообщает мне .9 - .8999999999999995 = 0,00000000000000055511151231257827? - PullRequest
8 голосов
/ 02 ноября 2009

Когда я набираю это в непосредственном окне Visual Studio 2008:

? .9 - .8999999999999995

Это дает мне в качестве ответа:

0.00000000000000055511151231257827

В документации сказано, что двойное имеет точность 15-16 цифр, но дает результат с 32 цифрами точности. Откуда вся эта дополнительная точность?

Ответы [ 6 ]

41 голосов
/ 02 ноября 2009

Там есть только 15-16 цифр в ответе. Все эти ведущие нули не в счет. Число на самом деле больше похоже на 5.5511151231257827 & times; 10 -16 . Часть мантиссы содержит 15-16 цифр. Показатель степени (-16) служит для смещения десятичной точки на 16 знаков, но не меняет количество цифр в общем числе.

Редактировать

После получения некоторых комментариев мне стало интересно, что на самом деле происходит. Я подключил соответствующий номер к этому IEEE-754 конвертеру . Потребовалось время округлить последние «27» до «30», но я не думаю, что это меняет результаты.

Преобразователь разбивает число на три двоичные части:

Знак: 0 (положительный)
Экспонент: -51
Значение: 1,0100000000000000000000000000000000000000000000000000 (двоичный файл для 1,25 10 )

Итак, это число составляет 1,01 2 & times; 2 -51 или 1,25 10 & times; 2 -51 . Поскольку хранятся только три значащие двоичные цифры, это предполагает, что Ларс может что-то делать. Они не могут быть «случайным шумом», так как они одинаковы при каждом преобразовании числа.

Данные свидетельствуют о том, что единственная сохраненная цифра - «5» Ведущие нули берутся из показателя степени, а остальные, казалось бы, случайные цифры - из вычислений 2 -51 .

17 голосов
/ 02 ноября 2009

Вы должны прочитать: Что должен делать каждый ученый Знать об арифметике с плавающей точкой .

В основном все сводится к тому, что числа с плавающей точкой хранятся с конечной точностью. Вы должны сделать сравнение с некоторой дельтой.

if(.9 - .8999999999999995 <= 0.0001)
  //close enough to be equal
14 голосов
/ 02 ноября 2009

Начальные нули не являются значимыми / являются частью точности (что касается числа с плавающей запятой - математически говоря, они являются значительными). Ведущие нули обусловлены показательной частью внутреннего представления числа с плавающей запятой.

Часть 55511151231257827 (которая имеет значение и или мантисса ) имеет 17 десятичных цифр, что достаточно близко к 15-16 цифрам.

@ Ларс Д: То, что вы считаете правильным, верно только в контексте вопроса. .9 - .8999999999999995 работает с плавающей точкой со значением 0,625 и степенью -50. Взятие 0,625 * 2 -50 приводит к 5,5511151231257827e-16. Теперь, вне контекста исходного вопроса, у нас есть число с 17 значащими цифрами, которое действительно является нашим лучшим двоичным приближением 0,0000000000000005. Тем не менее, эти ведущие нули все еще не являются значимыми с точки зрения представления числа с плавающей запятой.

4 голосов
/ 02 ноября 2009

? .9 - .8999999999999995

Этот процесс вычитания с 15-16 значащими цифрами дает

+0,0000000000000005

Остальные цифры - просто ошибки округления. Однако, поскольку компьютер всегда сохраняет 15-16 значащих цифр после первой ненулевой цифры, отображаются ошибки округления, и вы получаете много конечных случайных цифр, полученных в результате ошибок округления. Таким образом, результат содержит 16 значащих цифр из операции вычитания плюс 16 цифр из хранилища результата, что дает 32 цифры.

3 голосов
/ 02 ноября 2009

«Плавающая» часть «с плавающей точкой» означает, что вы приближаетесь к 5,5511151231257827 * 10 ^ (- 16). Это не совсем то, как оно представлено, потому что, конечно, все это делается в двоичном виде под капотом, но дело в том, что число представлено значащими цифрами, плюс число, которое представляет, как далеко сдвинуть основание (десятичную точку). Как всегда, википедия может дать вам более подробную информацию:

(Вторая ссылка более конкретно ориентирована на ваш конкретный случай.)

0 голосов
/ 02 ноября 2009

Я думаю, это потому, что в двоичной системе число 5 является периодическим, поскольку оно не делится на 2. И тогда применимо то, что сказал Марк Рушаков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...