Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

String representations of floating point values can lead to incorrect conclusions about the precision of the values. For example, consider converting a value of type float to the type double, a widening primitive conversion. Refer to the guideline FLP10-J. Do not cast primitive integer types to floating-point types without range checks for more details about such conversions. When the value of the float variable must be represented exactly using the double type, an explicit assignment is more appropriate than first converting the floating point value to a String and then to a double-point numbers should not be compared or inspected. If they are used, significant care needs to be taken to ensure expected behavior.

Noncompliant Code Example (String Comparison)

This noncompliant code example attempts a string-based comparison of a floating-point number.

Code Block
bgColor#FFCCCC

int i = 1;
String s = Double.valueOf(i / 1000.0).toString();
if (s.equals("0.001")) {
  // ...
}

However s actually contain the string "0.0010". Consequently, the comparison unexpectedly fails.

Noncompliant Code Example (Regex)

This noncompliant code example attempts to mitigate the extra trailing zero by using a regular expression on the string before comparing it.

Code Block
bgColor#FFCCCC

int i = 1;
String s = Double.valueOf(i / 1000.0).toString();
s = s.replaceFirst("[.0]*$", "");
if (s.equals("0.001")) {
  // ...
}

Thie comparison does succeed on this code.

However, the comparison fails on this similar code, which uses 1/10000.0 instead of 1/1000incorrectly compares the decimal string literal generated by 1/10000.0. The string produced is not 0.00010 but 0001 but rather 1.0E-4.

Code Block
bgColor#FFCCCC

int i = 1;
String s = Double.valueOf(i / 10000.0).toString();
s = s.replaceFirst("[.0]*$", "");
if (s.equals("0.0001")) {
  // ...
}

Compliant Solution (String Comparison)

This compliant solution uses the BigDecimal class to avoid precision lossthe conversion into scientific notation. It then performs a numeric comparison, which passes as expected.

Code Block
bgColor#ccccff

int i = 1;
BigDecimal d = new BigDecimal(Double.valueOf(i / 100010000.0).toString());
if (d.compareTo(new BigDecimal("0.0010001")) == 0) {
  // ...
}

Risk Assessment

Relying on Comparing or inspecting the string representation of floating-point types can result in imprecise valuesvalues may have unexpected results.

Guideline

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FLP09

NUM11-J

low

Low

likely

Likely

medium

Medium

P6

L2

Automated Detection

TODO

Related Vulnerabilities

HV-192

Bibliography

Wiki Markup
\[[API 2006|AA. Bibliography#API 06]\] 
\[[JLS 2005|AA. Bibliography#JLS 05]\]


Android Implementation Details

Comparing or inspecting the string representation of floating-point values may have unexpected results on Android.

Bibliography


...

Image Added Image Added Image AddedFLP08-J. Do not construct BigDecimal objects from floating-point literals      Floating Point (FLP)      Object Orientation (OBJ)