比较 Ruby on Rails 中两个几乎相同的 BigDecimal 数字

Comparing two virtually identical BigDecimal numbers in Ruby on Rails

提问人:Ely 提问时间:2/13/2015 最后编辑:Ely 更新时间:5/31/2015 访问量:774

问:

我遇到了一个小问题,我真的很想理解。我用来比较两个应该相同的 BigDecimal 数字。它们实际上只是极小的一部分,见下文:assert_equal

-#<BigDecimal:7f4b40e8de78,'0.4021666666 6666666666 666666667E2',36(45)>
+#<BigDecimal:7f4b40e85db8,'0.4021666666 6666666666 6666668E2',36(63)>

我使用是为了不使测试用例失败。所以我得到了一个合理的解决方法。我确实想知道是否有可能让它相等:assert_in_delta

assert_equal (241.30.to_d/6), model.division_function

该模型的作用完全相同。它将 value 的 BigDecimal 除以数组的长度,即 。division_function241.36

精度似乎存在非常微小的差异。 我想知道它可能来自哪里? 有没有办法更准确地控制精度?

编辑我正在使用 Mongoid。值得注意的是,Mongoid 提供 BigDecimal 作为字段类型,但它被存储为字符串。但是,我不认为这是问题所在。我相信这是 Ruby 的东西。

编辑我举了一个例子,暗示这是一个 Ruby 问题,与 Rails 没有直接关系。请看下面:

irb(main):041:0* amount1 = BigDecimal("241.3")
=> #<BigDecimal:7f49bcb03558,'0.2413E3',18(18)>
irb(main):042:0> amount2 = BigDecimal("1800")
=> #<BigDecimal:7f49bcaf3400,'0.18E4',9(18)>
irb(main):043:0> rate = amount1 / amount2
=> #<BigDecimal:7f49bcae8398,'0.1340555555 5555555555 5555556E0',27(45)>
irb(main):044:0> rate * amount2 #should return amount1 = 241.3, but it does not :-(
=> #<BigDecimal:7f49bcad6a30,'0.2413000000 0000000000 00000008E3',36(45)>
irb(main):045:0> 
Ruby 精度 相等 Bigdecimal

评论

0赞 Cary Swoveland 2/13/2015
您可以使用 Rational 类中的方法进行数学运算。
0赞 Ely 2/13/2015
正如我在帖子中提到的,division_function只是以与方法调用中的第一个参数相同的方式对两个属性进行除法。一个字段是 BigDecimal,另一个字段是数组的整数大小。我将尝试举一个简单的例子。assert_equal
0赞 Ely 2/13/2015
@CarySwoveland:谢谢你的提示。不知道。很高兴知道。但是,我依赖于BigDecimal,因为不幸的是,Rational在Rails框架中不支持数据类型。因此,在这种特殊情况下,我不能使用 Rational。
2赞 Ely 5/14/2015
我投票将这个问题作为题外话关闭,因为它不是一个错误,答案无助于解决问题。

答:

3赞 Ely 2/13/2015 #1

我向 Ruby 核心团队报告了这个错误。但是,这不是您在拒绝响应中看到的错误。

BigDecimal 虽然提供了任意精度,但不能精确地表示 1/3 这样的数字。因此,在某些算术过程中,您可能会遇到不精确性。

您可以在 Ruby 中使用 Rational 来获取确切的数字。如果您希望保持结果准确,请在进行算术时小心。