kdb*_*man 2 ruby floating-point precision bigdecimal
某些浮点数具有二进制浮点表示的固有不准确性:
> puts "%.50f" % (0.5) # cleanly representable
0.50000000000000000000000000000000000000000000000000
> puts "%.50f" % (0.1) # not cleanly representable
0.10000000000000000555111512312578270211815834045410
Run Code Online (Sandbox Code Playgroud)
这不是什么 新鲜事.但为什么红宝石BigDecimal也表现出这种行为呢?
> puts "%.50f" % ("0.1".to_d)
0.10000000000000000555111512312578270211815834045410
Run Code Online (Sandbox Code Playgroud)
(我正在使用rails速记.to_d而BigDecimal.new不仅仅是为了简洁,这不是特定于rails的问题.)
问题:为什么"0.1".to_d仍然会出现10 -17的错误?我认为目的BigDecimal明确是为了避免这样的不准确?
起初我认为这是因为我将一个已经不准确的浮点转换0.1为BigDecimal,并且BigDecimal只是无损地表示不准确.但我确保我使用的是字符串构造函数(如上面的代码片段所示),这应该可以避免这个问题.
编辑:
更多的调查表明,BigDecimal内部仍然干净利落.(很明显,因为否则这将是一个非常广泛使用的系统中的一个巨大的错误.)这是一个仍然显示错误的操作示例:
> puts "%.50f" % ("0.1".to_d * "10".to_d)
1.00000000000000000000000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)
如果表示是有损的,那将显示与上面相同的误差,只是移动了一个数量级.这里发生了什么?