In an application I am working some numbers get converted and saved from long(18 digits) to float/double. These numbers are like Reference/Id's but not used for calculations. Recently I noticed some discrepancies in data being stored as float/double. I am trying to understand if the behavior is due to what floating point numbers call significant digits and maybe a simple explanation for the same.
My questions based on below program are
NOTE : After my research on this topic , I do now understand that floating point numbers are by their nature inaccurate and should not be used to represent things that require accurate representations. Still I feel a bit confused about the above behavior and significant digits.
public class Main
{
public static void main(String[] args) {
System.out.printf( "1. Float value of 50000000115 is : %,f. Expected output was 50000000115.000000 \n", 50000000115f );
System.out.printf( "2. Float value of 50000000116 is : %,f. Expected output was 50000000116.000000 \n", 50000000116f );
System.out.printf( "3. Float value of 50000000117 is : %,f. Expected output was 50000000117.000000 \n\n", 50000000117f );
System.out.printf( "4. Float value of 2175863596593954381 is : %,f. Expected output was 2175863596593954381.000000 \n\n", 2175863596593954381f );
System.out.printf( "5. Float.MAX_VALUE: %,f\n\n", Float.MAX_VALUE );
System.out.printf( "6. Double value of 50000000115 is : %,f\n", 50000000115d );
System.out.printf( "7. Double value of 50000000116 is : %,f\n", 50000000116d );
System.out.printf( "8. Double value of 50000000117 is : %,f\n\n", 50000000117d );
System.out.printf( "9. Double value of 2175863596593954381 is : %,f. Expected output was 2175863596593954381.000000 \n\n", 2175863596593954381d );
System.out.printf( "10. Double.MAX_VALUE: %,f\n\n", Double.MAX_VALUE );
System.out.printf( "11. Float value of number gives expected result till 7 digits ie 12345678 is : %,f\n", 12345678f );
System.out.printf( "12. Float value of number gives expected result till 7 digits ie 11111111 is : %,f\n", 11111111f );
System.out.printf( "13. Double value of number gives expected result till 16 digits ie 1122334455667788 is : %,f\n", 1122334455667788d );
System.out.printf( "14. Double value of number gives expected result till 16 digits ie 1111222233334444 is : %,f\n", 1111222233334444d );
}
}
Output of above program
Float value of 50000000117 is : 49,999,998,976.000000. Expected output was 50000000117.000000
Float value of 2175863596593954381 is : 2,175,863,554,941,386,750.000000. Expected output was 2175863596593954381.000 000
Float.MAX_VALUE: 340,282,346,638,528,860,000,000,000,000,000,000,000.000000
Double value of 50000000115 is : 50,000,000,115.000000
Double value of 50000000117 is : 50,000,000,117.000000
Double value of 2175863596593954381 is : 2,175,863,596,593,954,300.000000. Expected output was 2175863596593954381.0 00000
Double.MAX_VALUE: 179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000.000000
Float value of number gives expected result till 7 digits ie 12345678 is : 12,345,678.000000
Java’s Float
type (IEEE-754 binary32) effectively has two components:
The smallest unit (within range) that keeps the number of units within range is used.
For example, with 50,000,000,115, we cannot use a unit size of 2048 (212), because 50,000,000,115 is about 24,414,062 units of 2048, which is more than 16,777,215 units. So we use a unit size of 4096.
50,000,000,115 is exactly 12,207,031.278076171875 units of 4096, but we can only use an integer number of units, so the Float
value closest to 50,000,000,115 is 12,207,031 units of 4096, which is 49,999,998,976.
The other values in your question are represented similarly, but Java’s rules for formatting numbers with %,f
result in limited numbers of decimal digits being used to show the value. So, in some of your examples, we see trailing zeros where the actual mathematical value of the internal number is different.
For Double
(IEEE-754 binary64), the two components are: