floating-pointdoubleieee-754

Is the maximum safe integer representable in IEEE double format 2⁵³ or 2⁵⁴?


I have seen in multiple posts that max safe integer representable in IEEE double format is 253:

But there is this one post which says it's 254:

https://stackoverflow.com/a/12445693

Range within which all integers can be represented (including boundaries)

  • 254 as an upper bound
  • -254 as a lower bound

Is this answer wrong or am I missing something?

Edit:

Above post seems to be corrected now.


Solution

  • But there is this one post which says it's 2^54: https://stackoverflow.com/a/12445693

    Range within which all integers can be represented (including boundaries) 2^54 as an upper bound -2^54 as a lower bound

    Is this answer wrong or am I missing something?

    You're not missing something. The first integer that IEEE 754 double-precision binary floating point ("double") can't represent is 2^53 + 1, which is well within the claimed -2^54..2^54 bounds. It's probably a typo, since all integers in the range -2^53..2^53 (inclusive) can be represented. From 2^53 onward, only multiples of 2 can be represented (so 2^53 + 2 is fine, but not 2^53 + 1). Since JavaScript uses this form of double, it's easy to see this in action:

    const x = 2**53;
    const y = x + 1;
    console.log(x.toLocaleString()); // 9,007,199,254,740,992
    console.log(y.toLocaleString()); // 9,007,199,254,740,992 -- the same
    console.log(x === y);            // true
    const z = x + 2;
    console.log(z.toLocaleString()); // 9,007,199,254,740,994

    With a double, 2^53 - 1 is the last so-called "safe" integer, where "safe" is defined as "you can add 1 to it and get the next integer." (In fact, JavaScript even has a constant for the value 2^53 - 1: Number.MAX_SAFE_INTEGER.) The next integer you get when you add 1 is (of course) 2^53 — the first integer at which the format can no longer handle every distinct integer. Starting with 2^53, a double can only count by twos: 2^53, 2^53 + 2, 2^53 + 4, ... That is, at that point it can only store multiples of 2. (And then later, it can only count by fours [multiples of 4], and then later only by eights [multiples of 8], etc.)

    For completeness: The format can (exactly) represent much larger integers, it's just that at that magnitude, it can't represent all of them, because the format uses a base value (mantissa) and an exponent, and when you reach 2^53, the exponent is such that only even numbers (multiples of 2) can be represented. Later the exponent rolls over again and only multiples of 4 can be represented, etc.

    Let's visualize this a bit. IEEE-754 is fairly complex, but let's take a simplified example (which isn't IEEE-754) just for the purposes of explanation. Suppose we have four bits to store an exponent and eight bits to store a mantissa, and let's say we only store whole numbers. That means with exponent = 1, we can store the values 0 through 255:

    CONCEPTUAL, *NOT* IEEE-754!
    
    Exponent (binary)    Mantissa (binary)   Result Value (decimal)
    0 0 0 1              0 0 0 0 0 0 0 0       0
    0 0 0 1              0 0 0 0 0 0 0 1       1
    0 0 0 1              0 0 0 0 0 0 1 0       2
    ...
    0 0 0 1              1 1 1 1 1 1 1 0     254
    0 0 0 1              1 1 1 1 1 1 1 1     255
    

    We're maxed out in the mantissa, so we sacrifice precision for range by using exponent = 2 and making the mantissa multiples of 2. Now we can only count by twos:

    CONCEPTUAL, *NOT* IEEE-754!
    
    Exponent (binary)    Mantissa (binary)   Result Value (decimal)
    0 0 0 2              0 0 0 0 0 0 0 1       2
    0 0 0 2              0 0 0 0 0 0 1 0       4
    ...
    0 0 0 2              0 1 1 1 1 1 1 1     254
    0 0 0 2              1 0 0 0 0 0 0 0     256
    0 0 0 2              1 0 0 0 0 0 0 1     258
    ...
    0 0 0 2              1 1 1 1 1 1 1 0     508
    0 0 0 2              1 1 1 1 1 1 1 1     510
    

    Notice that we can represent the value 256 precisely, even though it's out of the range the mantissa could handle on its own (0-255), because with the exponent we take the mantissa value (128) and double it to get 256. That's exactly what happens with 2^53 in a double. But we can't represent 257, because at that magnitude we can only handle multiples of 2. That's what happens with 2^53 + 1 in a double, we can't represent it. We can represent 2^53 + 2 though.