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?
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
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
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 2 24 . The closest you can get to 10.1 in the 32-bit format is 5295309•2 -19 , which is 10.1000003814697265625.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.