Это не имеет ничего общего с последней цифрой 5, а также с преобразованием десятичного значения в значение с плавающей запятой двойной точности.
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
По сути, десятичное число должно быть представлено в ограниченном двоичном формате, который может приближаться только к определенным десятичным значениям, что приводит к потере точности. Это может вызвать странное поведение, как вы видели.
Лучше всего объяснить это, показывая вам ... Marshal.dump(1.025)
сбрасывает значение Float и показывает значение немного ближе к тому, что оно есть на самом деле: 1.0249999999999999 . 1.025.to_r
предоставит вам дробь, которая представляет двоичное значение. Вы можете использовать произвольно точную десятичную библиотеку BigDecimal, чтобы преобразовать это:
ruby-1.9.2-p180 :060 > (BigDecimal.new("2308094809027379.0") / BigDecimal.new("2251799813685248.0")).to_s('F')
=> "1.024999999999999911182158029987476766"
Когда определенные десятичные дроби преобразуются в этот «приблизительный» формат двоичных чисел, они будут представлены по-разному, возможно, более точно. Итак, вы могли заметить, что 1.085.round(2)
приводит к 1.09 , как и следовало ожидать.
Это отсутствие точности в математике с плавающей запятой означает, что никогда не будет целесообразно использовать значения с плавающей запятой для расчетов в валюте или даже в качестве временных контейнеров для денежных значений. Для данных, связанных с деньгами, следует всегда использовать типы данных произвольной точности.
Как бывший разработчик чрезвычайно крупной финансовой компании, я постоянно был шокирован тем, как редко этот совет учитывается и как часто используется плавающее или двойное число в финансовом программном обеспечении. Большинство программистов в этой отрасли, с которыми я говорил, не знают, что числа с плавающей запятой и двойники никогда не должны хранить денежные ценности. Так что не думайте, что вы слишком за кривой; -)
ТЛ; др
Использовать BigDecimal: BigDecimal.new("1.025").round(2)
=> "1.03"