继此问题之后:
我想计算1/1048576并获得正确的结果,即0.00000095367431640625。
使用BigDecimal
的/
会截断结果:
require 'bigdecimal'
a = BigDecimal.new(1)
#=> #<BigDecimal:7fd8f18aaf80,'0.1E1',9(27)>
b = BigDecimal.new(2**20)
#=> #<BigDecimal:7fd8f189ed20,'0.1048576E7',9(27)>
n = a / b
#=> #<BigDecimal:7fd8f0898750,'0.9536743164 06E-6',18(36)>
n.to_s('F')
#=> "0.000000953674316406" <- should be ...625
这让我感到惊讶,因为我以为 BigDecimal
应该可以正常工作。
要得到正确的结果,我必须使用带有显式精度的 div
:
n = a.div(b, 100)
#=> #<BigDecimal:7fd8f29517a8,'0.9536743164 0625E-6',27(126)>
n.to_s('F')
#=> "0.00000095367431640625" <- correct
但我真的不太理解那个 precision(精确度) 参数。为什么我要指定它,以及我需要使用什么值才能得到未截断的结果?
这甚至是否有资格作为“任意精度浮点十进制算术”?
此外,如果我通过以下方式计算上述值:
a = BigDecimal.new(5**20)
#=> #<BigDecimal:7fd8f20ab7e8,'0.9536743164 0625E14',18(27)>
b = BigDecimal.new(10**20)
#=> #<BigDecimal:7fd8f2925ab8,'0.1E21',9(36)>
n = a / b
#=> #<BigDecimal:7fd8f4866148,'0.9536743164 0625E-6',27(54)>
n.to_s('F')
#=> "0.00000095367431640625"
我得到了正确的结果。为什么?
(1.0/3).is_a?(Float) #=> true
,BigDecimal.new(1)/BigDecimal.new(3)
可以写成BigDecimal.new(1)/3
((BigDecimal.new(1)/3).is_a?(BigDecimal) #=> true
),甚至是BigDecimal.new(1)/Rational(3)
。 - Cary Swovelandn.to_s('F')
返回比n
更高的精度,这表明BigDecimal
对象包含更多的信息。你想花时间研究BigDecimal
吗?一个好的起点是 BigDecimal#to_s。另外,你能解释一下(BigDecimal.new(1)/3).finite? #=> true
的意思吗? - Cary Swoveland(BigDecimal.new(1)/3).finite? #=> true
的意思吗?" - 根据文档,只有NAN
和INFINITY
返回false
。 - Stefann=a/b
返回10个有效数字,而n.to_s
返回12个。请忘记我提到“有限”的参考。解释我脑海中的胡言乱语需要太多的话,而且会非常无聊。 - Cary Swovelandinspect
还显示了 12 个数字,最后两个数字由一个空格分隔,就在E-6
的前面,即:'0.9536743164 06E-6'
= 0.953674316406 × 10⁻⁶。 - Stefan