Search code examples
javascriptbigint

Why BigInt(2 ** 100) does return a correct result in Chrome, Firefox, Safari


I would expect the number that I pass to BigInt has already overflowed before the BigInt creation, yet the result is correct. What is the reason, and can I rely on this for other powers of 2 (my use case)?


Solution

  • That is because the JavaScript number type follows the IEEE 754 standard for floating point numbers. These numbers are stored like this:

    • Sign bit (in your example +1)
    • Exponent (in your example 100)
    • Fractional part (in your example .0)

    ... to represent a number like sign * (1 + fractional part) * 2 ** exponent. In your case, that number is +1 * (1 + .0) * 2 ** 100.

    You can see that it can store powers of two exactly.

    You can't completely depend on it, though. This format is fixed size and so can only represent a finite number of numbers. The largest power of two that can be represented is 2 ** 1023. Trying to do BigInt(2 ** 1024) will throw a RangeError, because floating point numbers that are too large to be represented in 64 bits are represented with a special Infinity value.

    You are not going to get an inexact value, though, if that's the most important aspect for you.

    Should you need to deal with larger values, I suggest storing the exponent as a number and then doing 2n ** BigInt(my_exponent) when you need the BigInt. (Or BigInt(2) ** BigInt(my_exponent)`).