3

BigDecimal在红宝石中遇到了一种奇怪的行为。为什么这个打印错误?

require 'bigdecimal'

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

2 回答 2

3

BigDecimal 并不声称具有无限精度,它只是提供对正常浮点范围之外的精度的支持:

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

但是 BigDecimal 值仍然具有有限数量的有效数字,因此该precs方法

前言

返回两个整数值的数组。

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

如果您查看以下内容,您会发现事情开始出错c

>> c.to_s
=> "0.19607843137254901960784313725E2"

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

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

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

当然,这个技巧只适用于有理数,所以任何花哨的东西(如根或三角函数)都超出了界限。

于 2013-06-08T20:27:13.710 回答
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
于 2013-06-08T20:24:10.600 回答