Versions Compared

Key

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

String representations of floating point values may 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 INT03-J. Do not cast numeric types to wider floating-point types without range checking for more details about such conversions. If 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 converts a value of type float to a value of type double. The float variable contains the equivalent of 1/3 (0.3333333432674408). However, the default string representation can mislead a programmer into thinking that the correct value is 0.33333334. Consequently, the double variable may acquire an imprecise value. The imprecise value arises from the default precision used for converting floating point numbers to a string.

Code Block
bgColor#FFCCCC

double d;
float f = 1/3f; // Contains the value 0.33333334
d = Double.valueOf(String.valueOf(f)); // Now contains the value 0.33333334

Compliant Solution

This compliant solution assigns the value of type float to the double variable directly.

Code Block
bgColor#ccccff

double d;
float f = 1/3f; // Contains the value 0.3333333432674408 
d = f; // Assigned the value 0.3333333432674408

Noncompliant Code Example

This noncompliant code example obtains the result of 1/1000.0 and represents it as a String. However, even though the resulting value is precise, an extra zero digit is appended at the end. Any operations on the string, such as comparisons, may yield incorrect results.incorrectly compares the decimal string literal generated by 1/10000.0. The string produced is not 0.0001 but rather 1.0E-4.

Code Block
bgColor#FFCCCC

int i = 1;
String s = Double.valueOf (i / 100010000.0).toString(); // s contains 0.0010
if (s.equals("0.0010001")) { // Fails
  // Do something
}

Noncompliant Code Example

...

.

...

.

...

.

...


}

Compliant Solution (String Comparison)

Code Block
bgColor#FFCCCC

int i = 1;
String s = Double.valueOf (i / 10000.0).toString(); // s contains 0.0010
s = s.replaceFirst("[.0]*$", "");
// ...

...

This compliant solution uses the BigDecimal class and strips the trailing zeros so that future operations do not failto avoid the 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()).stripTrailingZeros();
if (d.compareTo(new BigDecimal("0.0010001")) == 0) { // Passes
  // Do something...
}

Risk Assessment

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

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FLP05

NUM11-J

low

Low

likely

Likely

medium

Medium

P6

L2

Automated Detection

TODO

Related Vulnerabilities

HV-192

References

Wiki Markup
\[[API 06|AA. Java References#API 06]\] 
\[[JLS 05|AA. Java References#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 AddedFLP06-J. Check floating point inputs for exceptional values      07. Floating Point (FLP)      FLP30-J. Do not use floating point variables as loop counters