在Ruby中,计算数字e时出现意外结果

时间:2017-01-30 08:24:40

标签: ruby

在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?这是一个错误还是什么?

2 个答案:

答案 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