Operator precedence

Figure 129. Precedence of * and / + over + and - Slide presentation
Code
IO.println(2 - 4 + 7);

// Same precedence for - and +     
// Evaluiation left-to-right:
// Equivalent to (2 - 4) + 7
IO.println(2 + 3 * 5);

// precedence of * over +
// Equivalent to 2 + (3 * 5)     
Result
5
17

exercise No. 50

Miraculous addition

Q:

Consider:

Code Result
int max = Integer.MAX_VALUE;  //2147483647    
IO.println(max + 1);
-2147483648
int max = Integer.MAX_VALUE;
IO.println(0L + max + 1);
2147483648
int max = Integer.MAX_VALUE;
IO.println(max + 1 + 0L);
-2147483648

This is strange: 0L + max + 1 differing from max + 1 + 0L violates the commutative law know from algebra. And why does adding 0 makes a difference in the first place? Explain these three outcomes.

A:

  1. The term max + 1 yields an overflow: Adding 1 to the already largest possible int value transitions to its smallest possible 4 byte 2-complement counterpart:

     2147483647           01111111_11111111_11111111_11111111
    +         1         + 00000000_00000000_00000000_00000001
    ———————————         —————————————————————————————————————
    -2147483648           10000000_00000000_00000000_00000000
  2. Due to the + operator's right associativity 0L + max + 1 is being evaluated as (0L + max) + 1. The starting expression 0L + max forces an int to long widening of max but still retaining its value:

               0L          00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L
    + 2147483647         +                                     01111111_11111111_11111111_11111111
    ————————————         —————————————————————————————————————————————————————————————————————————
      2147483647L          00000000_00000000_00000000_00000000_01111111_11111111_11111111_11111111L

    Adding 1 now becomes a long operation:

    + 2147483647L          00000000_00000000_00000000_00000000_01111111_11111111_11111111_11111111L
               1                                               00000000_00000000_00000000_00000001
    ————————————         —————————————————————————————————————————————————————————————————————————
      2147483648L          00000000_00000000_00000000_00000000_10000000_00000000_00000000_00000000L

    We thus avoid the overflow problem.

  3. The expression max + 1 + 0L is being evaluated as (max + 1) + 0L thus suffering from the original overflow. Adding 0L just turns an already erroneous int value of -2147483648 into a long.

Figure 130. A binary operator's operands evaluation priority Slide presentation
Code
int i = 2;

// Left hand operand evaluation priority
int j = (i=3) * i;

IO.println(j);
Result
9

See Evaluate Left-Hand Operand First.


Figure 131. left to right or right to left Slide presentation
int i, j, k;

// Right to left evaluation order,
// equivalent to i = (j = (k = 4))
i = j = k = 4;
...
// Left to right evaluation order,
// equivalent to IO.println((i + j) + k)
IO.println(i + j + k);

Figure 132. Operator precedence references Slide presentation

exercise No. 51

Evaluating a sum

Q:

Consider:

Code
int a = 3;
IO.println(++a + a);
int a = 3;
IO.println(a + ++a);
Result
8
7

Explain these two different outcomes.

A:

We consider the evaluation order for both snippets:

++a + a :

The center + has got one operand ++a to its left and another a to its right. Both will be evaluated left to right before being summed up. Thus at first a gets incremented by 1 due to ++a leaving us with a value of 4. The right a operand just stays as is at 4. Then both values left and right add up to the final value of 8.

a + ++a :
  1. The binary + operator takes the value 3 from its left operand a.

  2. Due to higher precedence of unary ++ over binary + the variable a gets incremented from 3 to 4: The value of the expression ++a is thus 4.

  3. The binary + operator takes the value 4 from its right operand ++a resulting in 7.

Figure 133. + acting as string concatenation operator Slide presentation
Code
// '+' as arithmetic operator
IO.println(4 + 7 + 3)
// '+' as String concatenation operator
IO.println("Get" + " the " + "vibe");
Result
14
Get the vibe

Figure 134. Implicit string conversion and concatenation Slide presentation
Code
IO.println("No. of groups: " + 44);
Result
No. of groups: 44
  1. Converting the int value of 44 into a string "44".

  2. Concatenating the two strings "No. of groups: " and "44" into "No. of groups: 44".