Рубиновая точность поплавка - PullRequest
8 голосов
/ 05 сентября 2011

Как я понимаю, Ruby (1.9.2) с плавающей точкой имеют точность 15 десятичных цифр. Следовательно, я ожидаю, что округление с плавающей точкой x до 15 знаков после запятой будет равно x . Для этого расчета это не так.

x = (0.33 * 10)
x == x.round(15) # => false

Между прочим, округление до 16 мест возвращает true.

Не могли бы вы объяснить это мне?

Ответы [ 2 ]

9 голосов
/ 06 сентября 2011

Часть проблемы заключается в том, что 0.33 не имеет точного представления в базовом формате, потому что оно не может быть выражено серией 1/2 n терминов. Таким образом, при умножении на 10 число, немного отличающееся от 0.33 , умножается.

В этом отношении 3.3 также не имеет точного представления.

Часть первая

Когда числа не имеют точного представления в виде основания-10, при преобразовании наименее значащей цифры, для которой была информация в мантиссе, будет остаток. Этот остаток будет распространяться вправо, возможно, навсегда, но это в значительной степени бессмысленно. Кажущаяся случайность этой ошибки обусловлена ​​той же самой причиной, которая объясняет, по-видимому, непоследовательное округление, которое вы заметили, и Matchu заметил. Это во второй части.

Часть вторая

И эта информация (самые правые биты) не выровнена аккуратно с информацией, передаваемой одной десятичной цифрой, поэтому десятичная цифра, как правило, будет несколько меньше, чем ее значение, если бы исходная точность была выше.

Вот почему преобразование может округляться до 1 с 15 цифрами и до 0.x с 16 цифрами: потому что более длинное преобразование не имеет значения для битов справа от конца мантиссы.

2 голосов
/ 06 сентября 2011

Ну, хотя я не уверен в деталях того, как Ruby обрабатывает плавающие внутри, я знаю, почему этот конкретный фрагмент кода не работает на моем компьютере:

 > x = (0.33 * 10)
=> 3.3000000000000003
 > x.round(15)
=> 3.300000000000001

Первый знак с плавающей запятой сохраняет по 16 десятичных разрядов в общей сложности 17 цифр по любой причине. Итак, округление до 15 отбрасывает эти цифры.

...