Порядок операций вопрос в рубине
Я инициализирую экземпляр класса, который проверяет равенство двух формул.
Расчетные значения формулы фактически равны:
RubyChem::Chemical.new("SOOS").fw
=> 96.0
RubyChem::Chemical.new("OSSO").fw
= 96.0
Когда я создал новый класс для проверки равенства этих двух экземпляров, я был немного удивлен результатами:
x = RubyChem::BalanceChem.new("SOOS","OSSO")
x.balanced
=>false
y = RubyChem::BalanceChem.new("SOOS","SOOS")
y.balanced
=> true
метод инициализации RubyChem::BalanceChem находится здесь:
def initialize(formula1, formula2)
@balanced = RubyChem::Chemical.new(formula1).fw == RubyChem::Chemical.new(formula2).fw
end
Почему ruby не извлекает значения fw для формулы 1 и формулы 2 и не проверяет равенство этих значений? Каков порядок операций в Ruby и что делает Ruby? Я вижу, что мне не хватает понимания этой проблемы. Как я могу сделать эту работу? Заранее спасибо.
3 ответа
Вы, вероятно, не хотите проверять числа с плавающей запятой на равенство. Вместо этого вы должны сравнить дельты.
Попробуйте это в irb:
x = 1.000001
y = 1.0
x == y
(x-y).abs < 0.00001
Таким образом, вы найдете дельту типа 0,00001, которая, по вашему мнению, будет обрабатывать любые вариации арифметики с плавающей запятой, и использовать ее таким образом. Вы никогда не должны ==
поплавки.
В Ruby 1.8 есть ошибка при преобразовании чисел с плавающей точкой в строку. Иногда данная строка не является хорошим представлением числа с плавающей точкой. Вот пример с 0.56
:
0.5600000000000005.to_s == 0.56.to_s #=> true
# should have returned false, since:
0.5600000000000005 == 0.56 #=> false
Это объясняет, почему два явно идентичных результата на самом деле не идентичны.
Вы, вероятно, хотите выполнить сравнение с определенным пределом погрешности, выполнить некоторое округление перед выполнением сравнения или использовать точные типы, такие как BigDecimal
или же Rational
,
Это, вероятно, еще одна проблема, вызванная точностью с плавающей запятой.
Я могу заверить вас, что эти значения рассчитаны до равенства.
Смотрите приоритет оператора Ruby