我对Ruby BigDecimal
类型(即使具有不同的精度和小数位数长度)应该准确计算的理解是正确的,还是应该预期到浮点恶作剧?
我在Rails应用程序中的所有值都是BigDecimal
类型,并且我看到了一些错误(它们的小数长度不同),希望这只是我的方法而不是我的对象类型。
发布于 2010-06-15 04:56:14
在使用浮点运算时,有两个常见的陷阱。
的第一个问题是浮点数具有固定的精度。在实践中,这要么是1)对你来说没有问题,要么是2)灾难性的,或者3)介于两者之间。请考虑以下几点:
# float
1.0e+25 - 9999999999999999900000000.0
#=> 0.0
# bigdecimal
BigDecimal("1.0e+25") - BigDecimal("9999999999999999900000000.0")
#=> 100000000
精度差一亿!很严肃,对吧?
但精度误差仅为原始值的0.000000000000001%左右。这真的是由你来决定这是不是一个问题。但是这个问题可以通过使用BigDecimal
来解决,因为它具有任意精度。您唯一的限制是Ruby可以使用的内存。
的第二个问题是,浮点数不能准确地表示所有分数。特别是,它们在小数方面有问题,因为Ruby (和大多数其他语言)中的浮点是二进制浮点。例如,十进制分数0.2
是一个永远重复的二进制分数(0.001100110011...
)。无论精度是多少,这永远不能以二进制浮点数的形式准确存储。
当你对数字进行四舍五入时,这会产生很大的差异。考虑一下:
# float
(0.29 * 50).round
#=> 14 # not correct
# bigdecimal
(BigDecimal("0.29") * 50).round
#=> 15 # correct
BigDecimal
可以精确地描述小数。然而,也有一些分数不能用小数精确地描述。例如,1/9
是一个永远重复的小数(0.1111111111111...
)。
同样,当你舍入一个数字时,这会咬你一口。考虑一下:
# bigdecimal
(BigDecimal("1") / 9 * 9 / 2).round
#=> 0 # not correct
在这种情况下,使用十进制浮点仍然会产生舍入误差()。
一些结论:
如果您使用小数进行计算,
BigDecimal
,如果您需要任意精度浮点数,并且并不真正关心它们是十进制浮点还是二进制浮点数,则它也很有效。https://stackoverflow.com/questions/3039650
复制相似问题