在ruby中,我尝试用明确的公式计算e:
(1+(1/t))**t
在irb中,我写下了这个
按照我的预期,
(1.0+(1.0/100000000000000))**100000000000000
给了我2.716110034087023。我试着增加 第10次。
(1.0+(1.0/1000000000000000))**1000000000000000
给了我3.035035206549262而不是e。 (非预期结果)。好吧,我试着将数量增加10倍。
(1.0+(1.0/10000000000000000))**10000000000000000
这个结果是1.0 - (好吧这可能是语言边界)
但是,意外结果是什么意思3.035035206549262?这是一个错误还是什么?
答案 0 :(得分:3)
这不是一个错误,它是floats行为的方式。 Ruby浮点数为double precision,因此当您的公式使用1E-15或更小的值时,您不能指望任何精确的结果。
这也是为什么银行不使用浮点数而是使用整数代表较小单位(例如美分)的原因。
如果你想计算e
,你可以使用另一个公式(例如the sum of infinite series),它不依赖于功率非常大的非常小的浮点数。作为奖励,它收敛得非常快,因此17个术语足以实现浮点精度:
fact = 1.0
e = (1..17).inject(1) do |mem, i|
fact *= i
mem + 1/fact
end
puts e
#=> 2.7182818284590455
puts e-Math::exp(1)
#=> 4.440892098500626e-16
BigDecimal
也可以作为替代方案,但对于基本为1**∞
的公式来说,它无济于事。
但是有BigMath
。这将输出1000个有效数字e
:
BigMath.exp(1,1000).to_s('F')
#=> 2.718281828459045235360......
答案 1 :(得分:2)
意外结果3.035035206549262是什么意思?这是一个错误还是什么?
只有一个可表示浮点数的finit数,每个实数必须舍入到最接近的浮点数。
对于t = 10 ** 14
,术语1+(1/t)
应为1.00000000000001
,但实际上是:
1.0000000000000099920072216264088638126850128173828125
它仍然非常接近,区别在于:
1.00000000000001
- 1.0000000000000099920072216264088638126850128173828125
--------------------------------------------------------
0.0000000000000000079927783735911361873149871826171875
用该近似值完成计算得出:
1.00000000000000999 100,000,000,000,000 ≈2.71611003409
但是对于t = 10 ** 15
,最接近的浮点值是:
1.0000000000000011102230246251565404236316680908203125
差异要大得多:
1.000000000000001
- 1.0000000000000011102230246251565404236316680908203125
--------------------------------------------------------
- 0.0000000000000001102230246251565404236316680908203125
这种近似给出了:
1.00000000000000111 1,000,000,000,000,000 ≈3.03503520655