Because floating-point numbers can represent fractions, it is often mistakenly assumed that they can represent any simple fraction exactly. In fact, floating-point numbers are subject to precision limitations just as integers are, and binary floating-point numbers cannot represent all decimal fractions exactly, even if they can be represented in a small number of decimal digits.
In addition, because floating-point numbers can represent large values, it is often mistakenly assumed 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 may not change that value within the available precision.
Hence, floating-point variables should not be used as loop counters.
Noncompliant Code Example
In this noncompliant code example, a floating-point variable is used 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 number.
Code Block | ||
---|---|---|
| ||
for (float x = 0.1f; x <= 1.0f; x += 0.1f) { // ... } |
This loop is executed only nine times. (If the value of x
is printed inside the loop, the following values appear: 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.70000005, 0.8000001, 0.9000001.)
Compliant Solution
In this compliant solution, the loop counter is an integer from which the floating-point value is derived.
Code Block | ||
---|---|---|
| ||
for (int count = 1; count <= 10; count += 1) { float x = count/10.0f; // ... } |
Noncompliant Code Example
In this noncompliant code example, a floating-point loop counter is incremented by an amount that is too small to change its value given its precision.
Code Block | ||
---|---|---|
| ||
for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) { /* ... */ } |
This produces an infinite loop.
Compliant Solution
In this compliant solution, the loop counter is an integer from which the floating-point value is derived. Additionally, a double
is used instead of a float
to gain enough precision.
Code Block | ||
---|---|---|
| ||
for (int count = 1; count <= 10; count += 1) { double x = 100000000.0 + count; /* ... */ } |
Risk Assessment
Using floating-point loop counters can lead to unexpected behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FLP30-J | low | probable | low | P6 | L2 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C Secure Coding Standard as FLP30-C. Do not use floating point variables as loop counters.
References
Wiki Markup |
---|
\[[JLS 05|AA. Java References#JLS 05]\] [Section 4.2.3, Floating-Point Types, Formats, and Values|http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3] \[[Bloch 05|AA. Java References#Bloch 05]\] Puzzle 34: Down for the Count |
FLP02-J. Do not attempt comparisons with NaN 05. Floating Point (FLP) FLP31-J. Convert integers to floating point for floating point operations