Java Floating Point Imprecision

In this short tutorial we will look at Java floating point precision errors when working with floating point numbers in Java.

Java Floating Point Numbers

Out of the box two of Javas primitive types for representing decimal values are the Java primitive types float and double. These types implement the IEEE Standard for Floating-Point Arithmetic (IEEE 754) specification. However using these types can lead to issues that you should be aware of. Java Floating points numbers are approximations they can hold larger values than integers, however, integers are stored in computer memory as exact values.

In contrast to integers the Java floating point number is based on the IEEE 754 specification, which means that these types have an exponent, a sign bit and a fraction, they are not stored in computer memory as exact values. This representation cannot represent all real number precisely, and it is in this representation that results in loss of precision.

Java Floating Precision Issue

Consider the decimal 0.1 this value cannot be stored in a floating point variable accurately. Instead of a precise value we would get an approximation of the nearest value. Also consider the following example:

1
2
3
4
5
6
7
float f1 = 0.1f;
float f2 = 0.1f;
float f3 = 0.1f;
float f4 = 3f;

//expected 0.9 but get something like 0.90000004
System.out.println( (f1 + f2 + f3) * f4 );

We would expect the above calculation of (0.1 + 0.1 + 0.1) * 3 to equal 0.9 however, the result is more like 0.90000004. Consider, working on a financial application, would you be happy trusting these floating point types to keep you happily employed, of course not. Well what’s the solution, you could create your own money types, or conversion methods, or, alternatively you could use the Jabva BigDecimal type. Lets look at the same example using BigDecimal.

1
2
3
4
5
6
7
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.1");
BigDecimal bd3 = new BigDecimal("0.1");
BigDecimal bd4  = new BigDecimal("3");

//expected 0.9 and got 0.9
System.out.println( bd1.add(bd2).add(bd3).multiply(bd4));

The java.math.BigDecimal type used above, returns the expected result. It also provides us with options for setting the precision and the rounding mode.

Conclusion

In this short tutorial we looked at an issue of imprecision when working with floating point numbers in Java.