Converting 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
is , a widening primitive conversion. Refer to the guideline INT33-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 inappropriate. Note that this is a problem that results from the limited capacity of computers in representing floating point values preciselymore appropriate than first converting the floating point value to a String
and then to a double
.
Noncompliant Code Example
Wiki Markup |
---|
In this noncompliant code example, the programmer attempts to convert the fractional value {{1/3}} (represented by a variable of type {{float}}) to the {{double}} type. The correct representation of this fraction in floating point arithmetic is 0.33333334 (the last digit 4, is rounded up). When converted to {{double}}, instead of observing a value such as 0.3333333400000000 or 0.333333333333333, the programmer obtains an unexpected value because floating point arithmetic in Java _rounds to the nearest_, a mode defined by the IEEE 754 floating point standard. If the exact value lies midway between two valid floating point values, the lower one (with the least significant bit as 0) is chosen. If it is more than midway, a small positive error is introduced, else a small negative error. \[[Mak 02|AA. Java References#Mak 02]\] |
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
Code Block | ||
| ||
double d; float f = 1/3f; // Contains the value 0.333333343333333432674408 d = f; // NowAssigned contains the value 0.3333333432674408 |
Compliant Solution
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 resultsIf the exact value must be preserved, the string representation of the floating point number must be obtained. This can be converted to the double
type without losing the initial precision.
Code Block | ||
---|---|---|
| ||
double dint i = 1; floatString fs = Double.valueOf (i 1/3f/ 1000.0).toString(); // Contains the value 0.33333334 d = Double.valueOf(String.valueOf(f)); // Now contains the value 0.33333334 |
Risk Assessment
s contains 0.0010
if(s.equals(0.001)) { // Fails
// Do something
}
|
Compliant Solution
This compliant solution uses the BigDecimal
class and strips the trailing zeros so that future operations do not fail.
Code Block | ||
---|---|---|
| ||
int i = 1;
BigDecimal d = new BigDecimal(Double.valueOf (i / 1000.0).toString()).stripTrailingZeros();
if(s.equals(0.001)) { // Passes
// Do something
}
|
Risk Assessment
Relying on the string representation of floating point types can result in imprecise valuesConverting from float
to double
type when exact values are required can affect the precision of the converted value.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FLP05- J | low | likely | medium | P6 | L2 |
...
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.HV-192
References
Wiki Markup |
---|
\[[API 06|AA. Java References#API 06]\] \[[JLS 05|AA. Java References#JLS 05]\] \[[Mak 02|AA. Java References#Mak 02]\] Section 3.7 "Another Look at Roundoff Errors" |
...
FLP04-J. Check floating point inputs for exceptional values 07. Floating Point (FLP) FLP30-J. Do not use floating point variables as loop counters