I'd like to understand how i in this piece of code ends up being 99999904
99999904 has a simpler representation in binary than 99999900 (uses fewer significant digits), and since the latter needs more significant digits than can be stored in a float, Java has to use the nearest representable value instead.
99999900 in hex: 0x5F5E09C
What 24 significant binary digits look like in hex:
0x7FFFFF8
99999904 in hex: 0x5F5E0A0
Between the two nearest representable values 0x5F5E098 and 0x5F5E0A0, Java chose the latter according to the “nearest-even” rule. The two representable values are in fact equally close, but 0x5F5E0A0 has 0 for the last significant digit, and so is chosen according to this rule. You can check for yourself that 99999899 rounds down to 0x5F5E098 and 99999900 rounds up to 0x5F5E0A0.
With 24 significant binary digits to the float
type, all integers between 0 and 224-1 can be represented exactly. 224 happens to be also representable exactly (it has only one significant digit), but 224+1, or 16777217, is not representable exactly as a float
, and the integers above it are not automatically exactly representable as float
either.