Because floating-point numbers can represent fractions, programmers often mistakenly assume that they can represent any simple fraction exactly. In fact, floating-point numbers are subject to precision range limitations just as integers are. FurtherFurthermore, limited-precision binary floating-point numbers cannot represent all decimal fractions exactlydecimals precisely, even when the fractions decimals can be represented in a small number of decimal digits.
In addition, because floating-point numbers can represent large values, programmers often mistakenly assume that they can represent all digits of those values. To gain a large dynamic range, floating-point numbers maintain a fixed number of bits of precision and an exponent. Incrementing a large floating-point value might not change that value within the available precision.
Consequently, floating-point variables should must not be used as loop counters.
...
This noncompliant code example uses a floating-point variable as a loop counter. The decimal number 0.1 is a repeating fraction in binary and cannot be exactly represented as a binary floating-point numbercan not be precisely represented as a float
or even as a double
.
Code Block | ||
---|---|---|
| ||
for (float x = 0.1f; x <= 1.0f; x += 0.1f) { // System... out.println(x); } |
This loop executes only nine times. (If the value of x
is printed inside the loop, the following values appear: , and produces the following output:
Code Block |
---|
0.1 |
...
0.2 |
...
0.3 |
...
0.4 |
...
0.5 |
...
0.6 |
...
0.70000005 |
...
0.8000001 |
...
0.9000001 |
...
|
Compliant Solution
This compliant solution uses an integer loop counter from which the desired floating-point value is derived.
Code Block | ||
---|---|---|
| ||
for (int count = 1; count <= 10; count += 1) { float x = count/10.0f; // System.out..println(x); } |
Noncompliant Code Example
...