Reputation: 2183
I found a but in my code and after some searching I realized that some floating operations that I was performing produced the wrong results. So I typed the following loop:
float f = 0f;
for(int i =0; i<15; i++){
f+= 10.1f;
System.out.println(f);
}
But in the results I get unexpected additional decimal values:
10.1
20.2
30.300001
40.4
50.5
60.6
70.7
80.799995
90.899994
100.99999
111.09999
121.19999
131.29999
141.4
151.5
What is going on here and how do I prevent it?
Upvotes: 1
Views: 168
Reputation: 222274
Two operations in your code cause errors:
10.1f
to float
. This conversion is inexact because 10.1 cannot be exactly represented in the floating-point format Java uses.10.1f
to previous values of f
. In many of these additions, the exact sum will not fit completely in the floating-point format, so the result must be rounded.You can modify the loop to avoid accumulating errors:
for (int i = 0; i < 15; i++)
{
f = (i+1) * 101 / 10.f;
System.out.println(f);
}
When you write the code in this way, f
will still not be exactly 10.1•(i+1) in every iteration, but it will be the closest representable value. In this new version, (i+1) * 101
is calculated exactly, and 10.f
is exactly 10 because 10 is representable in the floating-point format. This means that the only error is in the division operation. That operation will return the representable value closest to the exact result.
Java uses IEEE-754 binary floating-point, 32 bits for float
and 64 bits for double
. In those formats, a number is represented, basically, as an integer times a power of 2. In the 32-bit format, the integer must have magnitude less than 224. The closest you can get to 10.1 in the 32-bit format is 5295309•2-19, which is 10.1000003814697265625.
Upvotes: 1
Reputation: 3353
The numbers are stored as binary, and at a certain precision the representation between binary and decimal is not perfect, essentially leading to 'rounding errors'. If precision is of importance in this scenario, try using BigDecimal instead
Upvotes: 3
Reputation: 13972
You can't "prevent" it. What you need to do instead is expect it and compensate.
See: What Every Computer Scientist Should Know About Floating-Point Arithmetic
Upvotes: 3