I'm reading the second chapter of the book Eloquent JavaScript. The author states that:
Any whole number less than 2^52 (which is more than 10^15) will safely fit in a JavaScript number.
I grabbed the value of 2^52 from wikipedia.
4,503,599,627,370,496
The value has to be less than 2^52, so I've substracted 1 from the initial value;
var max = 4503599627370495;
After defining the max variable I'm checking what's the value (I'm using Chrome 32.0.1700.77
).
console.log(max); // 4503599627370495
I'd like to see what happens when I go over this limit, so I'm adding one a couple of times.
Unexpectedly:
max += 1;
console.log(max); // 4503599627370496
max += 1;
console.log(max); // 4503599627370497
max += 1;
console.log(max); // 4503599627370498
I went over the limit and the calculations are still precise.
I tried the next power of two instead, 2^53, I didn't substract 1 this time:
9,007,199,254,740,992
var max = 9007199254740992;
This one seems to be a bigger limit, it seems that I can quite safely add and substract numbers:
max += 1;
console.log(max); // 9007199254740992
max += 1;
console.log(max); // 9007199254740992
max -= 1;
console.log(max); // 9007199254740991
max += 1;
console.log(max); // 9007199254740992
max -= 900;
console.log(max); // 9007199254740092
max += 900;
console.log(max); // 9007199254740992
I can assign even a bigger value to the max, however it loses precision and I can't safely add or substract numbers again.
Could you please explain precisely the mechanism that sits under the hood? An example of what happens with the bits after going above 2^52 would be really helpful.
This is not a strongly typed programming language. JS has an object Number
. You can even get an infinite number: document.write(Math.exp(1000));
.
document.write(Number.MIN_VALUE + "<br>");
document.write(Number.MAX_VALUE + "<br>");
document.write(Number.POSITIVE_INFINITY + "<br>");
document.write(Number.NEGATIVE_INFINITY + "<br>");
alert([
Number.MAX_VALUE/(1e293),
Number.MAX_VALUE/(1e292),
Number.MAX_VALUE/(1e291),
Number.MAX_VALUE/(1e290),
].join('\n'))
Hope it's a useful answer. Thanks!
UPDATE: max int is - +/- 9007199254740992
You can find some information on JavaScript's Number type here: ECMA-262 5th Edition: The Number Type.
As it mentions, numbers are represented as a 64-bit floating-point number, with 53 bits of mantissa (significant digits) and 11 bits for the exponent (IEEE 754). The result is then obtained with: mantissa * 2^exponent.
This means that up to 2^53 values can be represented in the mantissa (of those a few numbers have special meanings, and the others are positive and negative integers).
The number 2^53 (9007199254740992) can't be represented in the mantissa, and you have to use an exponent. As an example, you can represent 2^53 as (9007199254740992 / 2) * 2^1
, ie. mantissa = 9007199254740992 / 2 = 4503599627370496
and exponent = 1
.
Let's check what happens with 2^53+1 (9007199254740993). Here we have to do the same, mantissa = 9007199254740993 / 2 = 4503599627370496
. Oops, isn't this the same mantissa we had for 2^53? Looks like there's been some rounding error! :)
(Note: the above examples are not actually how it really works: the mantissa is always interpreted as having a dot after the first digit, which means that eg. the number 3 is actually stored as 1.5*2
. I omitted this in the above explanation to make it easier to follow.)
You can find some more information on floating-point numbers (in general) here: What Every Computer Scientist Should Know About Floating-Point Arithmetic.
You can think of 52 bits integer in JS, but remember that bitwise logical operators &
|
>>
etc.. will only deal with 32 less significant bits discarding the rest.
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