Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Math.E equals 0.99.... ^ max int

A friend showed me that (at least, in the google chrome console) the following statement prints true:

1/Math.pow(0.9999999999999999, Number.MAX_SAFE_INTEGER) === Math.E

And indeed, 1/Math.pow(0.9999999999999999, Number.MAX_SAFE_INTEGER) is 2.718281828459045.

This can't be a coincidence?!

Could someone explain what is going on behind the scenes to make this work?

According to wolfram alpha, the correct value should be approximately 1/0.40628 which is approximately 2.4613566998129373 -- very far off from Math.E. (I am assuming that wolframalpha is more precise in its calculations than javascript, but I may be wrong).

Any explanation would be appreciated.

Bonus: What is the true approximate mathematical value of that expression, I wonder? I found this:

n = 0.0000000000000001
(1 - n)^MAX_INT =  1 + (MAX_INT choose 2) * n + (MAX_INT choose 3) * n^2 + ... + n^MAX_INT 

but I have no idea how to approximate that.

I tested the above expression in wolfram alpha and got 2.46 as well.

like image 610
soktinpk Avatar asked Dec 14 '14 18:12

soktinpk


1 Answers

pow(x, y) is typically computed as exp(log(x) * y), so let's start there.

We have:

  • x = 0.9999999999999999, which rounds to x = 1 - eps (where eps == 2^-53).
  • y = 2^53 - 1 i.e. y = 1 / eps (approximately).

So we're actually calculating exp(log(1 - eps) * 1/eps).

The Taylor series expansion of log(1 - k) is -k - k^2/2 - ..., but in our case all the higher-order terms will be truncated.

So we have exp(-eps / eps), or exp(-1), which is 1 / e.


Demonstration:
1 - 0.9999999999999999                  //  1.1102230246251565e-16
Math.log(1 - 1.1102230246251565e-16)    // -1.1102230246251565e-16
1 / Number.MAX_SAFE_INTEGER             //  1.1102230246251568e-16

like image 160
Oliver Charlesworth Avatar answered Oct 09 '22 11:10

Oliver Charlesworth