在Ruby核心库中,有一个非常有用的Set
类。它可以存储任何类型的对象。
但是如您所知,浮点数(Ruby中的Float
)存在一些准确性问题。 1.2-1.0
不等于0.2
。
s = Set.new()
s.add(1.2-1.0)
s.add(0.2)
s.size
=> 2
是的,我可以使用BigDecimal
类型来获取准确的数字。但是有可能给Set
一个特定的比较函数,以便它可以忍受一个小错误(例如1e-9
)吗?
(我知道这个问题与语言无关。欢迎其他常用语言的解决方案)
答案 0 :(得分:1)
有趣的问题,我想我找到了一个潜在的解决方案,取决于你想做什么。 Ruby在引擎盖下使用Hash
来存储Set
的元素。在Ruby中,Hash
密钥相等性由方法hash
和eql?
定义。因此,如果您在Float
中重新定义这些方法(请注意!),您可以使Set
认为合理地关闭Float
s是相等的:
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