Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to explain this operator associativity?

According to this table, ++ has right to left associativity. So, I run this code:

int a = 5;
++a + ++a * ++a

and expect the expression to be 50 (as 8 + 7 * 6, increment starts from right to left). But the expression is evaluated from left to right (6 + 7 * 8) by Eclipse, and gives result as 62. I am new to this associativity in Java, and must be missing something obvious. Please help me understand this strange behavior.

EDIT: Thank you for your answers, but I have one more question now. It is that, as seen from @bizclop's code and tree answer, it is obvious that the associativity for ++ doesn't matter. Then, is there any use case for this associativity of ++/--?

like image 617
Gaurang Tandon Avatar asked Jun 18 '15 09:06

Gaurang Tandon


People also ask

What is meant by associativity of an operator?

Associativity is the left-to-right or right-to-left order for grouping operands to operators that have the same precedence. An operator's precedence is meaningful only if other operators with higher or lower precedence are present. Expressions with higher-precedence operators are evaluated first.

What is the operator that associativity from right to left?

b = a; Here, the value of a is assigned to b , and not the other way around. It's because the associativity of the = operator is from right to left. Also, if two operators of the same precedence (priority) are present, associativity determines the direction in which they execute.

What is the associativity of operator in the given grammar?

The associativity of operators is decided by checking the Type Of Recursion in the production. If the production has left recursion, then the operator is left associative. If the production has right recursion, then the operator is right associative.


2 Answers

There are two different things mixed up here: expression parsing and expression evaluation.

Let's start with the expression: ++a + ++a * ++a. What do we first have to do with it? Since operators + and * need two operands and ++ needs one, we have to figure out which operand goes with which operation. This is the expression parsing step, where precedence/associativity are applied.

  1. ++ has the highest precedence, so we can rewrite our expression as (++a) + (++a) * (++a)
  2. Next up it's *, so again we can add parentheses: (++a) + ((++a) * (++a))
  3. And lastly we have +, the lowest precedence of all, so for the sake of symmetry we can write: ((++a) + ((++a) * (++a)))

Note that we can represent this neatly as a tree:

   +
  / \
++   *
 |   | \
 a  ++ ++
     |  |
     a  a

So this is our evaluation tree based on precedence and associativity.

Note that in this case associativity didn't matter at all as all the operators had different precedence. Had our expression been 4 - 1 - 3 + 2, it would've been important to use associativity to reach (((4 - 1) - 3) + 2), as + and - have the same precedence.

Now comes the next step, evaluation. Evaluation always happens from left to right (even for assignments, though the rules are a bit quirky), but it happens left-to-right using the tree we've just built.

  1. So first of all we start evaluating the + operator, as it's on the top.
  2. We then go one level down to the left, as we evaluate the ++a on the left side of the + operator, (6)
  3. then we go to the right and start evaluating the * operation.
  4. The way we do it is to evaluate the second ++a, (7)
  5. then the third ++a (8)
  6. and then we multiply the result of steps 4 and 5 (this is the * operation evaluated), (56)
  7. and finally we add the result of step 6 to the result of step 2 (62)

...and we're done.

TL;DR: Precedence and associativity determine where to put parentheses but evaluation is always left-to-right.

15.7. Evaluation Order

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

like image 71
biziclop Avatar answered Sep 20 '22 11:09

biziclop


It is because multiplication operator * has higher precedence over the addition + operator.

The computation will be ++a + (++a * ++a) = 6 + 7 * 8

like image 37
Crazyjavahacking Avatar answered Sep 19 '22 11:09

Crazyjavahacking