为什么这个比较失败了?

时间:2014-04-19 02:39:42

标签: ruby floating-point

知道为什么会这样吗? a是一个BigDecimal。

a                               # => 87.6
(word_count * b).to_f           # => 87.6
a.to_f == (word_count * b).to_f # => false

2 个答案:

答案 0 :(得分:2)

我会向你解释为什么会发生这种情况,这是最初的问题。

首先要明白的是,irb上的返回值是对字符串的强制转换。所以,例如:

class A
  def to_s
    "return value"
  end
end
A.new
=> return value

此外,.to_s方法与比较方法无关。他们有两种不同的实现方式。

所以你可以这样:

class A
  def to_s
    "87.6"
  end
end

class B
  def to_s
    "87.6"
  end
end

A.new
=> 87.6
B.new
=> 87.6
A.new == B.new
=> false

浮点数很难比较。来自wikipedia

  

IEEE标准定义的浮点数的比较与通常的整数比较略有不同。负零和正零比较相等,并且每个NaN比较不等于每个值,包括其自身。除NaN以外的所有值都严格小于+∞且严格大于-∞。有限浮点数的排序方式与它们的值相同(在实数集中)。

     

粗略近似,IEEE二进制浮点数的位表示与其基数2对数成比例,平均误差约为3%。 (这是因为指数字段位于数据的更重要部分。)这可以在某些应用程序中使用,例如数字声音处理中的音量斜坡。

因此,作为个人观点,最好的事情永远不会比较浮点数的相等性。这将避免将来出现一些警告,即使你现在的逻辑是正确的。我建议在比较前截断或舍入它。

答案 1 :(得分:1)

我发现使其按预期工作的最佳解决方案是:

a.to_s.to_f

转换.to_s会截断数字,还有其他方法:

"%.2f" % a

(a * 100).to_i / 100.0