2

在 Ruby 核心库中,有一个非常有用的Set类。它可以存储任何类型的对象。

但如您所知,浮点数(Float在 Ruby 中)存在一些准确性问题。1.2-1.0不等于0.2

s = Set.new()
s.add(1.2-1.0)
s.add(0.2)
s.size
=> 2

是的,我可以使用BigDecimaltype 来获取精确的数字。但是是否有可能给出Set一个特定的比较函数,以便它可以承受一个小错误(例如1e-9)?

(我知道这个问题与语言无关。欢迎使用其他常用语言的解决方案)

4

1 回答 1

1

有趣的问题,我想我已经找到了一个潜在的解决方案,这取决于你想要做什么。Ruby 在底层使用 aHash来存储 a 的元素Set。在 Ruby 中,Hash键相等是由方法hasheql?. 因此,如果您在Float(caveat emptor!) 中重新定义这些方法,您可以使Set考虑合理地接近Floats 相等:

class Float

  def eql?(other)
    other.is_a?(Float) && self.round(9) == other.round(9)
  end

  alias :old_hash :hash

  def hash
    self.round(9).old_hash
  end

end

s = Set.new
s.add(0.2)
s.include?(0.2)       # => true
s.include?(1.2 - 1.0) # => true
s.include?(0.2001)    # => false
于 2012-04-15T14:12:44.953 回答