Subtraction, unlike addition or multiplication, is not associative. Associativity says that @ is associative if and only if (a @ b) @ c = a @ (b @ c), where @ is a binary operator.
Because subtraction isn't associative, there are two answers, depending on which subtraction you do first. If you evaluate the left subtraction first, as in: (12 - 6) - 6, the answer is 0.
If you start with the right subtraction: 12 - (6 - 6), the answer is 12.
Which one does Java pick? It picks the left subtraction first. We'll see why.
We can constrain this problem further. Suppose all the operators are the same, such as the subtraction operator. How does it decide which subtraction it must perform?
The answer depends on the associativity of the operator. Some operators are left associative. Others are right associative.
To understand associativity, we're going to play a game. Here are the rules.
Consider the expression: a -_{1} b -_{2} c -_{3} d -_{4} e.
We have four subtraction operators (they look funny because I've written subscripts on them---for now, ignore the subscripts). We must pick one to parenthesize. Left associativity says to pick the leftmost operator that isn't covered (i.e., not surrounded by parentheses).
I've subscripted the subtraction operators so we can identify them. For example, -_{1} refers to the leftmost subtraction operator, while -_{4} refers to the rightmost subtraction operator.
The rule is add a pair of parentheses at a time, eliminating one subtraction operator at a time.
The first pair of parentheses goes around a - b. In this example, a is the left operand, while b is the right operand. A subtraction operator, which is binary, requires two operands.
We can't make the parentheses surround anything larger. For example:
(a -_{1} b -_{2} c) -_{3} d -_{4} e. WRONG!
The above parenthesization is "wrong". Java permits it, but the rules of the game only allow one uncovered subtraction operator to be covered at a time.
((a -_{1} b) -_{2} c) -_{3} d -_{4} e.
The left operand for -_{2} is (a - b) which is a covered expression, and the right operand is c.
(((a -_{1} b) -_{2} c) -_{3} d) -_{4} e.
The left operand for -_{2} is ((a - b) - c) which is a covered expression, and the right operand is d.
((((a -_{1} b) -_{2} c) -_{3} d) -_{4} e).
The left operand for -_{2} is (((a - b) - c) - d) which is a covered expression, and the right operand is e.
When Java evaluates an expression where all the operators have the same precedence (a concept we'll explain in the next lesson), it uses the associativity of the operator to determine which subexpression to evaluate first.
Left associativity says to pick the leftmost uncovered operator (and its operands) to add parentheses to.
In reality, temporary values are used internally by Java to keep track of the computation. As the programmer, you don't have to worry about it. Java handles this for you.
Even so, it's good to know what right associativity is.
Here's the rule: if all operators have the same precedence and are right associative, then pick the rightmost uncovered operator to parenthesize.
For example, suppose Java had a $ operator (it doesn't, but pretend that it does), and you wanted to parenthesize a $ b $ c $ d $ e using right associativity.
What would the answer be?
It's (a $ (b $ (c $ (d $ e))))
For example, suppose you want to have Java evaluate x - y - z, but you want y - z to be evaluted first. Without parentheses, this wouldn't happen. You must add parentheses as in x - (y - z) to get it to evaluate y - z first.
When in doubt, add parentheses.