Math.E等于0.99 .... ^ max int

sok*_*npk 6 javascript floating-point

一位朋友告诉我(至少在谷歌Chrome控制台中)以下语句打印为true:

1/Math.pow(0.9999999999999999, Number.MAX_SAFE_INTEGER) === Math.E
Run Code Online (Sandbox Code Playgroud)

的确,1/Math.pow(0.9999999999999999, Number.MAX_SAFE_INTEGER)2.718281828459045.

这不是巧合吗?!

有人可以解释幕后发生的事情吗?

根据wolfram alpha,正确的值应1/0.40628近似2.4613566998129373- 大约- 非常远离Math.E.(我假设wolframalpha在计算中比javascript更精确,但我可能错了).

任何解释将不胜感激.

额外奖励:我想知道这个表达式的真正近似数学值是多少?我找到了这个:

n = 0.0000000000000001
(1 - n)^MAX_INT =  1 + (MAX_INT choose 2) * n + (MAX_INT choose 3) * n^2 + ... + n^MAX_INT 
Run Code Online (Sandbox Code Playgroud)

但我不知道如何近似.

我在wolfram alpha中测试了上面的表达式并得到了2.46它.

Oli*_*rth 7

pow(x, y)通常计算为exp(log(x) * y),所以让我们从那里开始.

我们有:

  • x = 0.9999999999999999,转到x = 1 - eps(哪里eps == 2^-53).
  • y = 2^53 - 1y = 1 / eps(大约).

所以我们实际上在计算exp(log(1 - eps) * 1/eps).

泰勒级数展开log(1 - k)-k - k^2/2 - ...,但在我们的情况下,所有的高阶项将被截断.

所以我们有exp(-eps / eps),或者exp(-1),是1 / e.


示范:

1 - 0.9999999999999999                  //  1.1102230246251565e-16
Math.log(1 - 1.1102230246251565e-16)    // -1.1102230246251565e-16
1 / Number.MAX_SAFE_INTEGER             //  1.1102230246251568e-16
Run Code Online (Sandbox Code Playgroud)


Sim*_*rne 4

这源于e 的原始特征

方程

然后使用以下属性:

  • MAX_SAFE_INTEGER= 2 53 -1,并且
  • 0.9999999999999999舍入为 1 - 2 -53

然后

1/(1-2 -53 ) = 1 + 2 -53 /(1-2 -53 ) = 1 + 1/(2 53 -1)

所以,

1/(1-2 -53 ) 2 53 -1 = [1 + 1/(2 53 -1)] 2 53 -1

这与 e 非常接近。