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.
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.