Некоторые числа с плавающей точкой имеют присущую неточность из двоичного представления чисел с плавающей точкой:Почему рубины BigDecimal показывают неточность представления, похожую на float?
> puts "%.50f" % (0.5) # cleanly representable
0.50000000000000000000000000000000000000000000000000
> puts "%.50f" % (0.1) # not cleanly representable
0.10000000000000000555111512312578270211815834045410
Это nothingnew. Но почему у рубина BigDecimal
также показано это поведение?
> puts "%.50f" % ("0.1".to_d)
0.10000000000000000555111512312578270211815834045410
(я использую рельсы обсчитывать .to_d
вместо BigDecimal.new
для краткости только, это не рельсы конкретный вопрос.)
Вопрос: Почему "0.1".to_d
еще показываются ошибки на порядок 10 -17? Я думал, цель BigDecimal
была явно, чтобы избежать таких неточностей?
Сначала я думал, что это было, потому что я был преобразование уже неточным плавающего 0.1
к BigDecimal
и BigDecimal
только без потерь, представляющий inaccuraccy. Но я убедился, что использую конструктор строк (как в приведенном выше фрагменте), что должно избежать проблемы.
EDIT:
Немного больше исследований показывают, что BigDecimal
действительно все еще внутри представляют собой вещи чисто. (. Очевидный, поскольку в противном случае это будет огромной ошибки в широко используемой системе) Вот пример с операцией, которая будет по-прежнему показывать сообщение об ошибке:
> puts "%.50f" % ("0.1".to_d * "10".to_d)
1.00000000000000000000000000000000000000000000000000
Если представление было с потерей данных, что бы показать та же ошибка, что и выше, просто сдвинута на порядок. Что здесь происходит?