Floating-point variables must not be used as loop counters. Limited-precision IEEE 754 floating-point types cannot represent
- all simple fractions exactly
- all decimals precisely, even when the decimals can be represented in a small number of digits.
- all digits of large values, meaning that incrementing a large floating-point value might not change that value within the available precision.
Noncompliant Code Example
This noncompliant code example uses a floating-point variable as a loop counter. The decimal number 0.1 cannot be precisely represented as a float
or even as a double
.
for (float x = 0.1f; x <= 1.0f; x += 0.1f) { System.out.println(x); }
Because 0.1f
is rounded to the nearest value that can be represented in the value set of the float
type, the actual quantity added to x
on each iteration is somewhat larger than 0.1
. Consequently, the loop executes only nine times and fails to produce the expected output.
Compliant Solution
This compliant solution uses an integer loop counter from which the desired floating-point value is derived.
for (int count = 1; count <= 10; count += 1) { float x = count/10.0f; System.out.println(x); }
Noncompliant Code Example
This noncompliant code example uses a floating-point loop counter that is incremented by an amount that is too small to change its value given the precision.
for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) { /* ... */ }
The code loops forever on execution.
Compliant Solution
This compliant solution uses an integer loop counter from which the floating-point value is derived. Additionally, it uses a double
to ensure that the available precision suffices to represent the desired values.
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 |
---|---|---|---|---|---|
NUM09-J |
low |
probable |
low |
P6 |
L2 |
Automated Detection
Automated detection of floating-point loop counters is straightforward.
Related Guidelines
FLP30-C. Do not use floating point variables as loop counters |
||||
FLP30-CPP. Do not use floating point variables as loop counters |
||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="1f056a08-02c0-4470-ad10-bcd8e80d84fb"><ac:plain-text-body><![CDATA[ |
[ISO/IEC TR 24772:2010 |
http://www.aitcnet.org/isai/] |
Floating-point Arithmetic [PLF] |
]]></ac:plain-text-body></ac:structured-macro> |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="aa0ca01b-9d66-4c0d-807a-94fba420046e"><ac:plain-text-body><![CDATA[ |
[[Bloch 2005 |
AA. Bibliography#Bloch 05]] |
Puzzle 34, Down for the count |
]]></ac:plain-text-body></ac:structured-macro> |
|
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="cd584696-95fe-4907-9fea-f3adb8b9392a"><ac:plain-text-body><![CDATA[ |
[[JLS 2005 |
AA. Bibliography#JLS 05]] |
[§4.2.3, Floating-Point Types, Formats, and Values |
http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3] |
]]></ac:plain-text-body></ac:structured-macro> |