2
votes

IEEE-754 64 bit double precision floating point can't represent the integer 9007199254740995 and it stores instead 9007199254740996. Why not 9007199254740994?

I'm wondering what rules define this process? Does the integer get rounded? Are the rounding rules defined for rounding numbers with fractional parts also applied for integers?

I don't think that JS simply discards the bits that can't be put into mantissa. The number 9007199254740995 in binary is represented as:

1 0000000000000000000000000000000000000000000000000001 1
  |                       52 bits                    |  
  ----------------------------------------------------

The first implicit bit is not stored. So if JS simply discarded the bits that can't be stored, we would have 51 zeros followed by 1, which would result in the number 9007199254740994. But instead we have 50 zeros followed by 10:

1 0000000000000000000000000000000000000000000000000010 0
  |                       52 bits                    |  
  ----------------------------------------------------

which is the number 9007199254740996. So some other transformations had to take place.

1
because it has not enough space to store the last bit. Numbers have 53bit of precision. It would take 54bit to properly represent 9007199254740993. Without this last bit it's 9007199254740992 - Thomas
@Thomas, yes, please see my note at the end of the question - Max Koretskyi
there is not rounding, JS simply runs out of space to write the bits that would be needed to properly describe this number, and you get the results without these bits. Maybe I don't get your question, because if you understand why this number can't be stored as it is, then what are you asking? - Thomas
@Thomas, please see my update - Max Koretskyi
Haven't you got the bit patterns for 9007199254740992 and 9007199254740994 mixed up in the question? - Thomas Padron-McCarthy

1 Answers

4
votes

Yes, the rounding rules are exactly the same for all floating point numbers, and has nothing to do with whether or not they are integers.

When the number can't be represented by the format, it is rounded to the nearest representable value; if it is exactly halfway between two such values, it is rounded to the nearest "even" number, which is the one with a 0 in the last place of the significand.

In the case of 9007199254740995, it is exactly half-way between two floating point numbers: 9007199254740994, with significand:

1 0000000000000000000000000000000000000000000000000001

and 9007199254740996, with significand

1 0000000000000000000000000000000000000000000000000010

In this case, 9007199254740996 is the even one, so the result is rounded to that.