Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: reordered text around nce / cs

...

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 be promoted to the type float before the multiplication occurs, resulting in loss of precision. (See NUM13-J. Avoid loss of precision 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); 
  }
}

In this case, numeric promotions require that big be promoted to the type float before the multiplication occurs, resulting in loss of precision. (See NUM13-J. Avoid loss of precision when converting primitive integers to floating-point.). This code outputs 2.0E9 rather than 1.999999999E9.

...

This compliant solution uses the double type, instead of float, as a safer means of handling the widening primitive conversion resulting from integer promotion:

Code Block
bgColor#ccccff
class Test{
  public static void main(String[] args){
    int big = 1999999999;
    double one = 1.0d; // Double instead of float
    System.out.println(big * one);
  }
}

This solution produces the expected output of 1.999999999E9, which is the value obtained when an int is assigned (implicitly cast) to a double.

...

This noncompliant code example shows integer promotion resulting from the use of the bitwise OR operator. Each byte array element is sign-extended to 32 bits before it is used as an operand. If it originally contained the value 0xff, it would contain 0xffffffff [Findbugs 2008]. This causes result to contain a value other than the concatenation of the four array elements. 

Code Block
bgColor#ffcccc
byte[] b = new byte[4];
...
int result = 0;
for (int i = 0; i < 4; i++) {
  result = (result << 8) | b[i];
} 

Each byte array element is sign-extended to 32 bits before it is used as an operand. If it originally contained the value 0xff, it would contain 0xffffffff [Findbugs 2008]. This causes result to contain a value other than the concatenation of the four array elements.

Compliant Solution (Left Shift)

...

Code Block
bgColor#ccccff
byte[] b = new byte[4];
...
int result = 0;
for (int i = 0; i < 4; i++) {
  result = (result << 8) | (b[i] & 0xff);
} 

...

This noncompliant code example performs a compound assignment operation. This operation involves an int value that contains too many significant bits to fit in the 23-bit mantissa of a Java float, causing the widening conversion from int to float to lose precision. The resulting value is frequently unexpected. 

Code Block
bgColor#FFCCCC
public class Expr {
  public static void main(String[] args) {
    int x = 2147483642; // 0x7ffffffa
    x += 1.0f; // x contains 2147483647 (0x7fffffff) after the computation
  }
}

The compound operation involves an int value that contains too many significant bits to fit in the 23-bit mantissa of a Java float, causing the widening conversion from int to float to lose precision. The resulting value is frequently unexpected.

Compliant Solution (Compound Addition and Assignment)

For defense defensive programming purposes, 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.

...

This noncompliant code example uses a compound right-shift operator for shifting the value of i, bit by bit. 

Code Block
bgColor#FFCCCC
short i = -1;
i >>>= 1;

Unfortunately, the value of i remains the same. The value of i is first promoted to an int. This is a widening primitive conversion, so no data is lost. As a short, -1 is represented as 0xffff. The conversion to int results in the value 0xffffffff, which is right-shifted by 1 bit to yield 0x7fffffff. To store the value back into the short variable i, Java then performs an implicit narrowing conversion, discarding the 16 higher-order bits. The final result is again 0xffff, or -1.

...

bgColor#FFCCCC

...

Compliant Solution (Compound Bit Shift and Assignment)

...