在IRB:
0.9999999999999998 == 1.0
# => false
0.99999999999999998 == 1.0
# => true
同时只显示inspect
值:
0.9999999999999998
# => 0.9999999999999998
0.99999999999999998
# => 1.0
在我的情况下,我的程序创建的值不幸是第一个,因此我在编写测试用例时遇到问题,该测试用例将值验证为等于1。
我决定使用以下选项:
round
次调用,但应用程序已经运行,我无法测试round
次调用您的推荐方法是什么?有没有办法我可以配置我的程序在十进制之后用十五个九等于1.0来处理0?感觉有点令人沮丧,因为小数点后的十六个9似乎是截止的 - 我只有一个短线。
答案 0 :(得分:3)
阅读本文,了解如何比较小的浮点差异:
http://c-faq.com/fp/fpequal.html
我将他们提出的解决方案转换为Ruby:
class Float
MY_EPSILON = 0.000000000000001
MY_TOLERANCE = 0.000000000000001
def eq_epsilon?(flt)
a = self
b = flt
(a - b).abs <= MY_EPSILON * a.abs
end
def self.reldif(a, b)
c = a.abs
d = b.abs
d = [c,d].max
d == 0.0 ? 0.0 : (a - b).abs / d
end
def eq_reldif?(flt)
Float.reldif(self, flt) <= MY_TOLERANCE
end
end
因此我们可以运行一些测试代码:
f1 = 0.99999999999999998
f2 = 0.9999999999999998
f3 = 0.999999999999998
[f1, f2, f3].each { |f|
p f.eq_epsilon?(1.0)
p 1.0.eq_epsilon?(f)
}
puts "--------------"
[f1, f2, f3].each { |f|
p f.eq_reldif?(1.0)
p 1.0.eq_reldif?(f)
}
输出:
true
true
true
true
false
false
--------------
true
true
true
true
false
false
然而,可能需要进行更多测试以确保其满足您的所有要求。