Проблема в том, что некоторые числа, которые мы можем легко записать в десятичном виде, не имеют точного представления в конкретном формате с плавающей запятой, реализованном текущим оборудованием. Случайный способ заявить это - все целые числа, но не все дроби, потому что мы обычно храним дробь с показателем 2**e
. Итак, у вас есть 3 варианта:
Закруглите соответственно. Необоснованный результат всегда очень близок, поэтому округленный результат неизменно «идеален». Это то, что делает Javascript, и многие люди даже не осознают, что JS делает все с плавающей запятой.
Использовать арифметику с фиксированной точкой. Руби на самом деле делает это действительно легко; это один из немногих языков, который плавно переходит на Class Bignum из Fixnum по мере увеличения чисел.
Используйте класс, предназначенный для решения этой проблемы, например BigDecimal
Чтобы рассмотреть проблему более подробно, мы можем попытаться представить ваш «7.3» в двоичном виде. 7 часть легка, 111, но как нам сделать .3? 111,1 - 7,5, слишком большой, 111,01 - 7,25, приближается. Оказывается, 111.010011 является «следующим ближайшим меньшим числом», 7.296875, и когда мы пытаемся заполнить пропущенный .003125, в конечном итоге мы обнаруживаем, что это просто 111.010011001100110011 ... навсегда, не представляемое в выбранной нами кодировке в конечной битовой строке. .