BigDecimal在乘法后失去精度

时间:2013-06-08 20:04:57

标签: ruby floating-point

我在ruby中遇到BigDecimal的奇怪行为。为什么打印错误?

require 'bigdecimal'

a = BigDecimal.new('100')
b = BigDecimal.new('5.1')
c = a / b
puts c * b == a #false

2 个答案:

答案 0 :(得分:3)

BigDecimal声称没有无限精度,它只是支持正常浮点范围之外的精度:

  

BigDecimal为非常大或非常准确的浮点数提供了类似的支持。

但BigDecimal值仍然具有有限的有效位数,因此precs method

  

<强> precs

     

返回一个包含两个整数值的数组。

     

第一个值是BigDecimal中的当前有效位数。第二个值是BigDecimal的最大有效位数。

如果你看一下c

,你可以看到事情开始变得糟糕
>> c.to_s
=> "0.19607843137254901960784313725E2"

这是一个很好的干净有理数,但是BigDecimal不知道,它仍然看不到将c视为有限的数字串。

如果您使用Rational,您将获得您期望的结果:

>> a = Rational(100)
>> b = Rational(51, 10)
>> c * b == a
=> true

当然,这种技巧仅适用于您使用Rational数字,因此任何花哨的东西(例如根或三角函数)都是超出界限的。

答案 1 :(得分:2)

这是正常行为,并不奇怪。

BigDecimal并不保证无限的准确性,它允许您指定任意准确度,这不是一回事。使用浮点内部表示不能以完全精度表示值100/5.1。无论使用多少位都无关紧要。

“大理性”方法可以实现它 - 但不会让您访问某些功能,例如平方根。

请参阅http://ruby-doc.org/core-1.9.3/Rational.html

# require 'rational' necessary only in Ruby 1.8
a = 100.to_r
b = '5.1'.to_r
c = a / b
c * b == a
# => true