Hi All, There are two examples related float precision. The only difference is the value of int i differs and both the example gives different results.

You'll have to know something about IEEE 754 floating-point encoding to really understand this issue completely.

But briefly, the most important point here is that a float value cannot represent every int value precisely. floats are 32 bits long, and ints are also 32 bits long--but some of the 32 bits in the float are used to store the exponent (i.e. the "power"), leaving the float with only 23 bits to store the number's actual significant digits (called the significand). One more significant digit will automatically be assumed for most numbers (see the IEEE 754 spec). Therefore, once your int value is large enough that it requires more than 24 significant binary digits to represent, you're very likely to lose precision.

The two numbers you used in your tests (1234567890 and Integer.MAX_VALUE) are examples of such large numbers. As a result, when you cast them to a float, the JVM will choose the closest representable float value to your int value.

For 1234567890, the closest float value is 1234567936. Other int values "close" to 1234567890 will also be mapped to a float value of 1234567936. (To be precise, all ints from 1234567872 to 1234568000 will be mapped to this value.) This loss of precision causes the non-equality you observed when you cast the float back to an int.

Integer.MAX_VALUE (2147483647) is a more interesting case. This will get mapped to a float value of 2^31, or 2147483648. (All numbers from 2147483584 to 2147483776 will be mapped to this value.) However, when you cast this float value back to an int, this is larger than the maximum value of an int, so the JVM maps it back to Integer.MAX_VALUE. Hence your equality test prints "true".

Note that your code will print "true" for int values that are exactly representable with a float. As already mentioned, 1234567936 is one such number. The next smaller one is 1234567808, and the next larger one is 1234568064.

Also, you won't get any loss of precision converting an int to a double, because a double uses 52 bits for its significand. However, you'll run into the same problem if you convert a long to a double.

Edit: I should also note that none of this stuff is on the SCJP exam, so don't worry about it. But some of you may find this stuff interesting. [ November 15, 2007: Message edited by: Kelvin Lim ]

SCJP 5.0

Mohit Jain
Ranch Hand

Joined: Jun 04, 2007
Posts: 74

posted

0

Kelvin Thanks a lot for such a nice description. By the way SCJP is an important step towards success in Java but its not the final destination. I really want to learn all this stuff well.

Please tell me what approach you have followed to learn all this stuff and how can I get to it apart from SCJP.