Ruby 一些“BigDecimal”值不';与“Float”不匹配`
一些Ruby 一些“BigDecimal”值不';与“Float”不匹配`,ruby,rspec,floating-point,Ruby,Rspec,Floating Point,一些bigdecimic值可以通过Rspec3中的eq与Float进行比较,但一些值不能进行比较 describe "compare BigDecimal with Float" do it { expect("83.79".to_d).to eq(83.79) } # => fail it { expect("83.75".to_d).to eq(83.75) } # => succeed end 为了避免错误,我使用了类似于eq(“83.79.To_d)的表达式
bigdecimic
值可以通过Rspec3中的eq
与Float
进行比较,但一些值不能进行比较
describe "compare BigDecimal with Float" do
it { expect("83.79".to_d).to eq(83.79) } # => fail
it { expect("83.75".to_d).to eq(83.75) } # => succeed
end
为了避免错误,我使用了类似于eq(“83.79.To_d)
的表达式
为什么第一个测试失败而第二个测试成功?您不应该尝试任何类型的浮点值严格相等测试。您必须始终使用
Float
处理不准确的内部表示问题,因此=
和=代码>不是很有用
考虑这一点:
'83.79'.to_d - 83.79
# => #<BigDecimal:7ff33fcea560,'-0.1E-13',9(36)>
'83.75'.to_d - 83.75
# => #<BigDecimal:7ff33fcee688,'0.0',9(27)>
然后选择delta(1e-12,本例中为
)以符合您的要求。“83.79”。to_d在内部表示法中精确表示分数8379/100,因为它使用基数10(或其幂),而“83.79”。to_f不是因为内部表示法使用基数2,所以它们不相等
这与83.75不同,因为在基数2和基数10中都精确地表示了is(这是83+1/2+1/4)
如果在同一表达式中混合使用大小数和浮点,则浮点将转换为最接近的大小数。。。因此,您实际上是在执行以下操作:83.79.to\u d
或换言之“83.79.to\u f.to\u d
由于“83.79.”to_f
不精确,而且由于大小数比浮点更精确,因此没有理由将其与“83.79.”to_d
匹配
但是,如果您以另一种方式强制转换,我希望平等适用:
expect("83.79".to_d.to_f).to eq(83.79)
这是因为我们可以合理地预期(最不令人惊讶的是)到f的转换将回答精确分数最近的浮点,无论是从精确的大十进制还是字符串表示。由于Ruby的大十进制和RSpec的存在,这不是一个标准问题的重复。“大十进制比浮点更精确”——事实上,有无限多的BigDecimal
s,但只有2**64float
s,因此BigDecimal
s比float
s多得多。
expect("83.79".to_d.to_f).to eq(83.79)