Basically floating point numbers are represented as:
digits * 2 ** movement
digits (the mantissa) has 52 bits (and 1 "hidden bit"), movement has 11 bits, and both together form a 64bit number (with 1 sign bit). Through that, you can represent all kinds of different numbers as you can store very large numbers (large positive movement), very small numbers (large negative movement), and integers (digits).
What is Number.MAX_SAFE_INTEGER ?
Integers can just be represented with movement being set in a way that the mantissa is actually the number itself, then digits contains the 52 + 1 bit number, and that can hold up to 2 ** 53 - 1
numbers (which is Number.MAX_SAFE_INTEGER
).
Now for larger numbers, you have to use movement, which basically means that you move the digits left or right, and therefore you lose accuracy.
(Imagine digits
would just take 8 bits)
number > digits | movement > result
// savely represented
11111111 > 11111111 | 0 > 11111111
// lost the last 1
111111111 > 11111111 | 1 > 111111110
// lost the two last 1s
1111111111 > 11111111 | 10 > 1111111100
What is Number.MAX_VALUE ?
If you set all bits of digits
and all bits of movement
, you get a number (2 ** 53 - 1
) that is moved by 2 ** 10 - 1
to the left, and that is the largest number that can be stored in the 64 bit, everything that is larger is Infinity
(which is represented as the movement being 2 ** 10 and the mantissa being 0).