Почему Visual Studio 2008 сообщает мне .9 - .8999999999999995 = 0,00000000000000055511151231257827?

StackOverflow https://stackoverflow.com/questions/1662600

Вопрос

Когда я печатаю это в окне Visual Studio 2008:

? .9 - .8999999999999995

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

0.00000000000000055511151231257827

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

Это было полезно?

Решение

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

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

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

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

Знак:0 (положительный)
Экспонента:-51
Значение:1.0100000000000000000000000000000000000000000000000000 (двоичный для 1.2510)

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

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

Другие советы

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

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

if(.9 - .8999999999999995 <= 0.0001)
  //close enough to be equal

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

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

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

? .9 - .8999999999999995

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

0.0000000000000005

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top