You are using the float
datatype.
This datatype is not able to precisely hold the value 0.525
. See this code for making it clear:
float value = (float) (0.5 * 1.05);
DecimalFormat df = new DecimalFormat("#.########################");
System.out.println(df.format(value));
This prints out:
0.5249999761581421
Rounding such a value with the mode RoundingMode.HALF_UP
will correctly yield 0.52
.
The double
value seems to be able to precisely store the value 0.525
:
double value = 0.5 * 1.05;
DecimalFormat df = new DecimalFormat("#.########################");
System.out.println(df.format(value));
This will print the expected value:
0.525
Rounding that value with the mode RoundingMode.HALF_UP
will now yield 0.53
!
Caution: Even the double
datatype does not store the value precisely!
Look at @MarkDickinson's comment. The stored value is 0.52500000000000002220446049250313080847263336181640625
which happens to be larger than 0.525
and only rounds by accident to the expected value.
So what to do?
The data types float
and double
are binary-based, whereas we humans tend to think decimal-based when dealing with numbers. Read the article "What Every Computer Scientist Should Know About Floating-Point Arithmetic" for much more information.
The solution is to use a decimal-based data type, which exists in BigDecimal
.