У меня есть вычисление, которое генерирует то, что, кажется, Плавание 22.23 и литеральные 22.23 как так:
some_object.total => 22.23
some_object.total.class => Float
22.23 => 22.23
22.23.class => Float
Но по некоторым причинам, следующее является ложью:
some_object.total == 22.23 ? true : false
Дурацкий, правильно?
Там некоторый механизм точности использует, который, возможно, не абсолютно прозрачен через вызов some_object.total?
Числа с плавающей запятой не могут точно представить все десятичные числа в пределах их диапазона. Например, 0,9 - это не совсем 0,9, это число, действительно близкое к 0,9, которое в итоге печатается так же, как и в большинстве случаев. По мере того, как вы выполняете вычисления с плавающей запятой, эти ошибки могут накапливаться, и вы получите что-то очень близкое к правильному, но не совсем равное ему. Например, 0,3 * 3 == 0,9
вернет false
. Так обстоит дело с каждым компьютерным языком, который вы когда-либо будете использовать - именно так работает двоичная математика с плавающей запятой. См., Например, этот вопрос о Haskell .
Чтобы проверить равенство с плавающей запятой, вы обычно хотите проверить, находится ли число в каком-то крошечном диапазоне от целевого значения. Так, например:
def float_equal(a, b)
if a + 0.00001 > b and a - 0.00001 < b
true
else
false
end
end
Вы также можете использовать класс BigDecimal в Ruby для представления произвольных десятичных чисел.
Если это тестовый пример, вы можете использовать assert_in_delta
:
def test_some_object_total_is_calculated_correctly
assert_in_delta 22.23, some_object.total, 0.01
end
Float # to_s
и Float # inspect
раунд. Попробуйте "%. 30f"% some_object.total
, и вы увидите, что это не совсем 22.23.
здесь происходит что-то еще. это из 1.8.7 irb
irb(main):001:0> class Test
irb(main):002:1> attr_accessor :thing
irb(main):003:1> end
=> nil
irb(main):004:0> t = Test.new
=> #<Test:0x480ab78>
irb(main):005:0> t.thing = 22.5
=> 22.5
irb(main):006:0> t.thing == 22.5
=> true