【发布时间】:2016-10-14 18:41:08
【问题描述】:
某些浮点数与二进制浮点表示存在固有的不准确性:
> puts "%.50f" % (0.5) # cleanly representable
0.50000000000000000000000000000000000000000000000000
> puts "%.50f" % (0.1) # not cleanly representable
0.10000000000000000555111512312578270211815834045410
这是nothingnew。但是为什么 ruby 的 BigDecimal 也会出现这种行为呢?
> puts "%.50f" % ("0.1".to_d)
0.10000000000000000555111512312578270211815834045410
(为了简洁起见,我使用 rails 简写 .to_d 而不是 BigDecimal.new,这不是特定于 rails 的问题。)
问题:为什么"0.1".to_d 仍然显示大约10-17 的错误?我认为BigDecimal 的目的是明确避免这样的错误?
起初我以为这是因为我将已经不准确的浮点 0.1 转换为 BigDecimal,而 BigDecimal 只是无损地表示不准确。但我确定我使用的是字符串构造函数(如上面的 sn-p),这应该可以避免这个问题。
编辑:
更多调查表明BigDecimal 仍然在内部清晰地表示事物。 (很明显,否则这将是一个非常广泛使用的系统中的巨大错误。)下面是一个操作仍然会显示错误的示例:
> puts "%.50f" % ("0.1".to_d * "10".to_d)
1.00000000000000000000000000000000000000000000000000
如果表示是有损的,那将显示与上述相同的错误,只是移动了一个数量级。这是怎么回事?
【问题讨论】:
标签: ruby floating-point precision bigdecimal