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.
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
.
1 - 0.9999999999999999 // 1.1102230246251565e-16
Math.log(1 - 1.1102230246251565e-16) // -1.1102230246251565e-16
1 / Number.MAX_SAFE_INTEGER // 1.1102230246251568e-16
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With