比较 RSpec 中小数值的正确方法?
Proper way to compare decimal values in RSpec?
我有这个检查预期数量的规范:
expect(animal_cost).to eq(0.7771118644067795e5)
我收到一条错误消息:
expected: 77711.18644067795
got: 0.7771118644067795e5
如您所见,我得到的数字与我预期的数字相同,所以我很困惑为什么会失败。如何设置规格?
animal_cost.class
是一个 BigDecimal。
[animal_cost] equals 0.7771118644067795e5
[...] it's a BigDecimal
这是一个浮点数问题。您的 BigDecimal
值为 0.7771118644067795e5 的 exact 值为:
77711.18644067795
另一方面,浮点数 77711.18644067795
的实际值为:(与大多数语言一样,Ruby 会截断浮点数)
77711.186440677949576638638973236083984375
根据比较,这些值可能会或可能不会被视为“相等”:
d = BigDecimal('0.7771118644067795e5')
f = 0.7771118644067795e5
d == f #=> true
f == d #=> true
d.eql?(f) #=> true
f.eql?(d) #=> false
后者 returns false
因为这就是 Float#eql?
的工作方式:
eql?(obj) → true or false
Returns true
only if obj
is a Float
with the same value as float
.
为了使测试通过准确的值,您应该使用 BigDecimal
而不是浮点数:
expect(animal_cost).to eq(BigDecimal('0.7771118644067795e5'))
就我个人而言,我会避免使用此类示例,因为您(显然)正在将结果复制到预期中。这个值是否正确并不明显。 (小数点后 11 位的“成本”对我来说似乎是错误的)尝试更改您的示例数据以获得可理解的结果,也可能是一个“整数”数字,例如70,000.
使用 rspec 验证浮点数的最佳方法是使用 be_within
匹配器。浮点数不能用二进制在数学上完全准确地表示。难免会有一些舍入误差。
在你的情况下,人们会写:
expect(animal_cost).to be_within(0.001).of(0.7771118644067795e5)
我有这个检查预期数量的规范:
expect(animal_cost).to eq(0.7771118644067795e5)
我收到一条错误消息:
expected: 77711.18644067795
got: 0.7771118644067795e5
如您所见,我得到的数字与我预期的数字相同,所以我很困惑为什么会失败。如何设置规格?
animal_cost.class
是一个 BigDecimal。
[animal_cost] equals
0.7771118644067795e5
[...] it's aBigDecimal
这是一个浮点数问题。您的 BigDecimal
值为 0.7771118644067795e5 的 exact 值为:
77711.18644067795
另一方面,浮点数 77711.18644067795
的实际值为:(与大多数语言一样,Ruby 会截断浮点数)
77711.186440677949576638638973236083984375
根据比较,这些值可能会或可能不会被视为“相等”:
d = BigDecimal('0.7771118644067795e5')
f = 0.7771118644067795e5
d == f #=> true
f == d #=> true
d.eql?(f) #=> true
f.eql?(d) #=> false
后者 returns false
因为这就是 Float#eql?
的工作方式:
eql?(obj) → true or false
Returns
true
only ifobj
is aFloat
with the same value asfloat
.
为了使测试通过准确的值,您应该使用 BigDecimal
而不是浮点数:
expect(animal_cost).to eq(BigDecimal('0.7771118644067795e5'))
就我个人而言,我会避免使用此类示例,因为您(显然)正在将结果复制到预期中。这个值是否正确并不明显。 (小数点后 11 位的“成本”对我来说似乎是错误的)尝试更改您的示例数据以获得可理解的结果,也可能是一个“整数”数字,例如70,000.
使用 rspec 验证浮点数的最佳方法是使用 be_within
匹配器。浮点数不能用二进制在数学上完全准确地表示。难免会有一些舍入误差。
在你的情况下,人们会写:
expect(animal_cost).to be_within(0.001).of(0.7771118644067795e5)