Numeric promotions are used to convert the operands of a numeric operator to a common type so that an operation can be performed. When using binary operators with mixed operand sizes, be aware that some of the narrower operands could be promoted to a wider type to match the type of the other operand. For example, in the expression a == 42, the field a, which is shorter than an int, will be promoted to an int before the comparison is carried out.
According to the Java Language SpecificationSection 4 (JLS)§4.2.2, "Integer Operations"
If an integer operator other than a shift operator has at least one operand of type
long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of typelong. If the other operand is notlong, it is first widened (§5.1.5) to typelongby numeric promotion (§5.6). Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of typeint. If either operand is not anint, it is first widened to typeintby numeric promotion.
Promotion Rules
The JLS Section 5§5.6, "Numeric Promotions" describes numeric promotion as the following:
- If any of the operands is of a reference type, unboxing conversion is performed. Then
- If either operand is of type double, the other is converted to double.
- Otherwise, if either operand is of type float, the other is converted to float.
- Otherwise, if either operand is of type long, the other is converted to long.
- Otherwise, both operands are converted to type int.
Widening conversions, resulting from integer promotions preserve , preserves the overall magnitude of the number. However, promotions in which the operands are converted from an int to a float or from a long to a double can cause unexpected loss of precision. (See guideline "NUM17-J. Beware of precision loss when converting primitive integers to floating-point" for more details.)
These conversions can happen with the following operators: multiplicative operators (%, *, /), additive operators (+, -), comparison operators (<, >, <=, >=), equality operators (==, !=), and the integer bitwise operators (&, |, ^).
...
Type coercion may occur when compound expressions are used with mixed operand types. Examples of compound assignment operators are +=, -=, *=, /=, &=, ^=, %=, <<=, >>=, >>>= and |=.
According to the JLS Section 15§15.26.2, "Compound Assignment Operators"
A compound assignment expression of the form
E1 op= E2is equivalent toE1 = (T)((E1) op (E2)), whereTis the type ofE1, except thatE1is evaluated only once.
...
When the operands are different types, multiple conversions may can occur. For example, when E1 is an int and E2 is either a long, a float, or a double, E1 is widened from type int to the type of E2 (before the "op"), followed by a narrowing conversion from the type of E2 back to type int (after the "op" , but before the assignment).
...
In this noncompliant code example, a variable of type int (big) is multiplied by a value of type float one. In this case, numeric promotions require that big is promoted to the type float before the multiplication occurs, resulting in loss of precision. (see See "NUM17-J. Beware of precision loss when converting primitive integers to floating-point".).
| Code Block | ||
|---|---|---|
| ||
class Test{
public static void main(String[] args){
int big = 1999999999;
float one = 1.0f;
// binary operation, loses precision because of implicit cast
System.out.println(big * one);
}
}
|
This code outputs 2.0E9 whereas, and not 1.999999999E9 as may be expected.
Compliant Solution (Multiplication)
...
To be safe, avoid using any of the compound assignment operators on variables of types byte, short, or char. Also, refrain from using a wider operand on the right hand side. In this compliant solution, all operands are of the Java type double.
...
Failing to consider integer promotions when dealing with floating-point and integer operands can result in loss of precision.
...
Automated detection of numeric promotion is straightforward. Determining which promotions may be are problematic is infeasible in the general case. A heuristic approach may could provide acceptable results.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Bibliography
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup |
...
" ac:schema-version="1" ac:macro-id="da94fcce-cad2-41bf-9834-d84c16053476"><ac:plain-text-body><![CDATA[ | [[Bloch |
...
2005 |
...
AA. |
...
Bibliography#Bloch |
...
05] |
...
] |
...
Puzzle |
...
9: |
...
"Tweedledum |
...
" | ]]></ac:plain-text-body></ac:structured-macro> | |||
| Puzzle 31: "Ghost of Looper" | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="64959f37-e9da-455f-a012-e96fd8cb2076"><ac:plain-text-body><![CDATA[ | [[Findbugs 2008 | AA. Bibliography#Findbugs 08]] | "BIT: Bitwise OR of signed byte value" | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6ac29340-82f6-4a1e-ae09-0bf7dbcc8f07"><ac:plain-text-body><![CDATA[ | [[JLS 2005 | AA. Bibliography#JLS 05]] | [§4.2.2, "Integer Operations" | http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.2 |
...
] | ]]></ac:plain-text-body></ac:structured-macro> |
| |
|
...
NUM17-J. Beware of precision loss when converting primitive integers to floating-point 03. Numeric Types and Operations (NUM) NUM19-J. Ensure that division and modulo operations do not result in divide-by-zero errors