Versions Compared

Key

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

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 type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6). Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int. If either operand is not an int, it is first widened to type int by numeric promotion.

Promotion Rules

The JLS Section 5§5.6, "Numeric Promotions" describes numeric promotion as the following:

  1. If any of the operands is of a reference type, unboxing conversion is performed. Then
  2. If either operand is of type double, the other is converted to double.
  3. Otherwise, if either operand is of type float, the other is converted to float.
  4. Otherwise, if either operand is of type long, the other is converted to long.
  5. 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= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is 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
bgColor#ffcccc
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>

 

§5.6, "Numeric Promotions"

 

§15.26.2, "Compound Assignment Operators"

...

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