
Using integer arithmetic to calculate a value for assignment to a floating-point variable may lead to loss of information. This can be avoided by converting one of the integers in the expression to a floating-point type. When converting integers to floating-point values, it is important to be aware that there can be loss of precision. (See guideline INT03-J. Avoid casting primitive integer types to floating-point types without range checks.)
Noncompliant Code Example
In this noncompliant code example, the division and multiplication operations take place on integers and the result gets converted to floating-point. This causes floating-point variables d
, e
, and f
to be initialized incorrectly because the operations take place before the values a
, b
and c
are converted to floating-point. The results of the operations are either truncated to the nearest integer, or they could overflow.
short a = 533; int b = 6789; long c = 4664382371590123456L; float d = a / 7; // d is 76.0 (truncated) double e = b / 30; // e is 226.0 (truncated) double f = c * 2; // f is -9.1179793305293046E18 because of overflow
Compliant Solution (Floating Point Literal)
This compliant solution eliminates the decimal error in initialization by ensuring that, at least, one of the operands to the division operation is of the floating-point type.
short a = 533; int b = 6789; long c = 4664382371590123456L; float d = a / 7.0f; // d is 76.14286 double e = b / 30.; // e is 226.3 double f = (double)c * 2; // f is 9.328764743180247E18
Compliant Solution
This compliant solution eliminates the initialization errors by storing the integers in the floating-point variables, then performing the arithmetic operations. This ensures that, at least, one of the operands is a floating-point number, and, consequently, the operation is performed on floating-point numbers.
short a = 533; int b = 6789; long c = 4664382371590123456L; float d = a; double e = b; double f = c; d /= 7; // d is 76.14286 e /= 30; // e is 226.3 f *= 2; // f is 9.328764743180247E18
Exceptions
FLP02-EX1: When the programmer intends to use integers before the conversion (for example, obviating the need to use the floor()
method), this choice should be clearly documented to help future maintainers understand that this behavior is intentional.
Risk Assessment
Improper conversions between integers and floating point values can yield unexpected results, especially from precision loss. In some cases, these unexpected results can involve overflow or undefined behavior.
Guideline |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FLP02-J |
low |
probable |
low |
P6 |
L2 |
Automated Detection
Automated detection is not feasible in the general case. Heuristic checking could be useful.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Related Guidelines
C Secure Coding Standard: FLP33-C. Convert integers to floating point for floating point operations
C++ Secure Coding Standard: FLP33-CPP. Convert integers to floating point for floating point operations
Bibliography
[[JLS 2005]] Section 5.1.2, Widening Primitive Conversion
FLP01-J. Take care in rearranging floating point expressions 07. Floating Point (FLP) FLP03-J. Range check before casting floating point numbers to narrower types