0

I'd like to understand how i in this piece of code ends up being 99999904 ?

long i = (long)(99999900f);
System.out.println(i);

I understand that floats are stored with decimals and are not the exact value they appear to be but I don't see how that could lead to the first digit being a 4 and not a 9 or something that would eventually round up to 99999900?

pp_
  • 3,435
  • 4
  • 19
  • 27
Randy
  • 295
  • 1
  • 9
  • 2
    Try `System.out.println(99999900f);` – Elliott Frisch Feb 20 '16 at 03:37
  • 9.9999904E7 Shortest comment to have ever explained something so clearly! Are all floating numbers stored in that format? i.e with 1 digit before the decimals ? Thanks – Randy Feb 20 '16 at 03:43
  • Nevermind, just tested a couple, seems that as the number grows we store more digits in the decimals, probably so that we can fit a larger number than what the size of a float is. Thanks again – Randy Feb 20 '16 at 03:46
  • There are [two parts](https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3) to floating point numbers. See also [Welcome to the Secret Robot Internet](http://www.smbc-comics.com/?id=2999). – Elliott Frisch Feb 20 '16 at 03:47
  • 1
    See [How many significant digits have floats and doubles in java?](http://stackoverflow.com/questions/13542944/how-many-significant-digits-have-floats-and-doubles-in-java). Try `99999900D`. –  Feb 20 '16 at 04:02
  • I looked for a while for a good duplicate before writing an answer, but the question this one has been closed as a duplicate of isn't it. The most upvoted answer there is http://stackoverflow.com/a/13542957/139746 and it does not really address large integers. – Pascal Cuoq Feb 20 '16 at 09:34

1 Answers1

1

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.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281