It's not safe to compare floats with the operator ==
float a = 1f - 0.9f; float b = 0.1f; System.out.println(a == b); // Wrong! System.out.println(Math.abs(b - a) < 0.001f); // Correct!
The above code will return:
false
true
Can you explain why?
The fact is that 0.1f is stored as 0.0999999999999999996 and displayed as 0.1
Look at this now:
float a = 3.666f; float b = 11/3f; System.out.println(a == b); // Wrong! System.out.println(Math.abs(b - a) < 0.001f); // Correct!
It prints again:
false
true
To compare two float we have to check that the precision (in this case 0.001) is greater than the absolute of the difference of the two float values.
The float are not a good solution to represent currency amounts. For example, what's the output of the following instruction?
System.out.println(1.04 - 0.1);
The output is:
0.9400000000000001
We can say that the attempt to be precise of a float or a double is at the cost of the accuracy. We can't have both.
But for currencies we need accuracy, so the solution is the class java.math.Bigdeciamal.
Now, look at this example:
BigDecimal bd1 = new BigDecimal("1.04"); BigDecimal bd2 = new BigDecimal("0.10"); BigDecimal bd3 = bd1.subtract(b2); System.out.println(bd3.toString());
The output is still wrong... why?
0.9400000000000000299760216648792265914380550384521484375
The right way to use BigDecimal for currencies is to round the values:
BigDecimal bd1 = new BigDecimal("1.04"); BigDecimal bd2 = new BigDecimal("0.10"); BigDecimal bd3 = bd1.subtract(bd2).setScale(2, BigDecimal.ROUND_HALF_EVEN); System.out.println(bd3.toString());
This time, it returns:
0.94
We can also compare the two decimal of the initial example:
BigDecimal bd1 = new BigDecimal("3.666"); BigDecimal bd2 = new BigDecimal("11"); BigDecimal bd3 = new BigDecimal("3"); BigDecimal bd4 = bd2.divide(bd3, 2, BigDecimal.ROUND_HALF_UP); System.out.println(bd4.compareTo(bd1));
The output is:
1
Copyright © 2013 Welcome to the website of Davis Fiore. All Rights Reserved.