This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Beginning Java and the fly likes simple operator precedence question Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "simple operator precedence question" Watch "simple operator precedence question" New topic
Author

simple operator precedence question

frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
If operands are evaluated before before any operators are applied( p33 RHE, 3.4 p.50 Mughal), and Unary and assignment operators associate right to left (Mughal), then where A =1,
a[++A] = a[++A]; we should have something like this happening:
first operands evaluated - a[++1] = a[++1], then operators applied right to left, so a[3] = a[2]. But this does not happen in real life. Instead we get something like a[2] = a[3]. How can this be if the prefix unary operator should be applied later and right to left???
Tony Alicea
Desperado
Sheriff

Joined: Jan 30, 2000
Posts: 3222
    
    5
Herb: Go to the Source :
The Java Language Specification.
---
Sheriff Tony


Tony Alicea
Senior Java Web Application Developer, SCPJ2, SCWCD
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
OK, that simple expression is really complex . Section 15.7.2 says that operands are evaluated before operators. The assignment operator associates right to left(15.26). BUT in the case where "=" is used and the operands of the "=" are array access expressions, those array access operands are evaluated left to right first(15.26.1), then we associate the "=" right to left. But the prefix increment operator has higher precedence than the "=" operator, so shouldn't it increment its operands first, which would be right to left ? This puts me back where I started with my original question...
Jyotsna Clarkin
Ranch Hand

Joined: Jan 26, 2001
Posts: 158
Hi Herb,
I think you've confused evaluation order and associativity.
Evaluation order in an expression is always left to right

operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
From JLS

Associativity relates to grouping; Right associativity implies grouping from right to left & NOT evaluation from right to left.
Finally the operator precedence table ranks
1. []
2. ++ (prefix)
3. =
Does this help??
regards,
Jyotsna

[This message has been edited by Jyotsna Clarkin (edited March 08, 2001).]
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
Let's make this even more simpler :
int x =1;
x = ++x - ++x;
Now there's 2 things to consider : evaluation of operands and application of operators. The operand is x and the operator is the unary prefix increment operator. First we evaluate the variable, then we apply the operator. It should be two distinct steps and the increment operator is like any other operator.
So, step 1 is:
1 = ++1 - ++1;
Then , step 2 would be apply the operators. The associativity rule is applied when operators have equal precedence which is the case here. The associativity of all unary operators is right to left. So we should have :
x = (++1 - (++1);
x = (3 -2 );
The JLS text supports this and Mughal supports this, but the VM says something else. Yes, I am confused. Please, tell me where exactly the mistake is in the reasoning and application of the rules.
Siva Prasad
Ranch Hand

Joined: Feb 22, 2001
Posts: 104
Originally posted by herb slocomb:
Let's make this even more simpler :
int x =1;
x = ++x - ++x;


The whole expression is evaluated from left to right. And the operands for '-' operator are two statements
st1: ++x (left hand side of - ) is incremented as it is a statement - x = x+1 and the result of this statement (x=2) is used. now the x value is 2
st2: ++x (right hand side of - ) is incremented as it is a statement - x = x+1 and the result of this statement (x=3 because the value of x was 2 after st1) is used.
now x value is 3
Now these two statements results were placed in the main expression like this
x = 2 - 3 which means x = -1
That's what you get the output.
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
OK, no one is addressing the rules of associativity, which is when operators have equal precedence they are evaluated right to left. See Mughal, Section 3.1
Siva Prasad
Ranch Hand

Joined: Feb 22, 2001
Posts: 104
Originally posted by herb slocomb:
OK, no one is addressing the rules of associativity, which is when operators have equal precedence they are evaluated right to left. See Mughal, Section 3.1

ok if that is so
what will be the output of this statement? (since '/' '*' abd '+' have equal precedence)
x = 20 / 4 * 5 + 2;
it is - 0? (20/28)
it is...27 ( 20/4 first and the result is multiplied by 5 and then finally 2 is added)
btw who is this mughal and what's the story?
Siva Prasad
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
Mughal is the great god of SCJP testing who gave us his holy book called A Programmer's Guide to Java Certification. The rules of associativity are different for binary operators than for unary operators. The example above involved binary operators only.
Jyotsna Clarkin
Ranch Hand

Joined: Jan 26, 2001
Posts: 158
Once again Herb
Mughal does NOT -repeat NOT- say that associativity is equal to evaluation order. Read the defintion for associativity (left & right)again.
Take this example
int i = 1;
i = ++i + ++i - i++;
Associativity rules say right to left for prefix unary operators. And left to right for postfix. GROUP them. That's all you do.
i = (++i) + (++i) - (i++);
Grouping right to left means start with the operand and move left to include as many elements that would allow you to apply the operator. Or in other words, gather togther all the elemnts that would make an meaningful expression.
For the unary operator this is ONE operand and ONE operator
Prefix (R->L)
++i ---> ++i) ----> (++i)
Postfix (L->R)
i++ ----> (i++ ---->(i++)
Now evaluate this
i = (++i) + (++i) - (i++);
Once gain we have 2 operators with equal precedence +,- and =.
But these are binary operators so grouping would mean that we include TWO operands and ONE operator.
Binary + operator (L->R)
( (++i) + (++i)) - (i++)
Binary - operator (L->R)
( ( (++i) + (++i)) - (i++))
Now you can evaluate all these "sub-expressions" to get the final = result
Binary = (L->R)
(i = result of subexpressions)
The associativity and precedence rules are there to help you evaluate multiple subexpressions such as these. Remember Evaluation ORDER is always left to right
Rules for binary/unary or postfix/prefix etc may well be different but they always apply to the required number of operands only.

This is what Mughal has said as well. I hope this helps clear some of the confusion.
regards,
Jyotsna

[This message has been edited by Jyotsna Clarkin (edited March 08, 2001).]
[This message has been edited by Jyotsna Clarkin (edited March 08, 2001).]
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
Yes, thankyou, exactly what I was looking for. What I've exactly struggled against is the fact Mughal gives these rules on associativity for unary operators but they are absolutley un-usefull as far as I can tell because I cannot construct any situation where unary associativity would make any difference. My best attempt was my post on this topic. Can anyone come up with a situation where unary associativity would make a difference? I tried (another posting) to construct one with Array indexs earlier but it made no difference. Wouldn't it better to say there is no associativity with unary operators??? To me that would have been clearer. To associate means to group something and to group something with itself is pointless. So, I'm trying to come up with a situation that would justify Mughal's statement, but really there is none. Really confusing is the distinction he makes between pre and post fix unary operators. To make a distinction means there is a difference in effect, but I see none.Anyway, thanks again for exactly what I was looking for.
By the way, evaluation of variables is first, then order of precedence is applied. If there are operators of equal precedence, then associativity is applied. I'm quite clear on this.
[This message has been edited by herb slocomb (edited March 08, 2001).]
[This message has been edited by herb slocomb (edited March 08, 2001).]
[This message has been edited by herb slocomb (edited March 08, 2001).]
[This message has been edited by herb slocomb (edited March 08, 2001).]
Jyotsna Clarkin
Ranch Hand

Joined: Jan 26, 2001
Posts: 158
Originally posted by herb slocomb:
By the way, evaluation of variables is first, then order of precedence is applied. If there are operators of equal precedence, then associativity is applied. I'm quite clear on this.

That would be evaluation of operands.
Yes, I just wanted to get this associativity stuff out of the way.
Andy Ceponis
Ranch Hand

Joined: Dec 20, 2000
Posts: 782
This has been a very helpful thread. For me at least.
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
Yes, "variables" being a subset of operands.
But are we agreed Mughal maybe goofed here in saying that post and prefix operators have different order of associativity. I'm hoping someone will prove me wrong and restore my confidence in Mughal.
[This message has been edited by herb slocomb (edited March 08, 2001).]
[This message has been edited by herb slocomb (edited March 08, 2001).]
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
A better example is:
int x = 1;
x = x++ - x++ * x++;
evaluated like this :
1) (x++)-(x++) * (x++);
2) ((x++)- ((x++) * (x++))); // "*" has higher precedence
3) ((x++) - ((1) * (2))); //evaluate innermost operands first, L to R)
4) 3 - 2 // this is wrong result because the leftmost x++ is evaluated first, but if that's the case the groupings and nested parentheses so abundently present on this posting don't have the usual meaning, which is that innermost parentheses are evaluated first. Somewhere in this topic something is wrong or inconsistent
[This message has been edited by herb slocomb (edited March 10, 2001).]
Jyotsna Clarkin
Ranch Hand

Joined: Jan 26, 2001
Posts: 158
Originally posted by herb slocomb:
A better example is:
int x = 1;
x = x++ - x++ * x++;
evaluated like this :
1) (x++)-(x++) * (x++);
2) (x++)- ((x++) * (x++)); // "*" has higher precedence
3) (x++) - ((1) * (2)); //evaluate innermost operands first, L to R)
4) 3 - 2 // this is wrong result but why ?

No Herb:
Once again you're confusing evaluation order with assoc. & precedence and everything else...
x = (x++) - (x++) * (x++) // assoc
x = 1 - 2 * 3 ----> (1 - (2 * 3)) // precedence
(x = (1 - 6))
x = -5 // answer!
Don't start substitution from the middle of an expression !!! I think that's where you're going wrong.
regards,
Jyotsna
frank davis
Ranch Hand

Joined: Feb 12, 2001
Posts: 1479
Here's maybe the source of confusion : Mughal says "operands are evaluated left to right before operators are applied". Since "++" is an operator, there are two steps, first evaluate; second apply the "++" operator. In applying the operator we use the normal rules of associativity and group everything nicely with nested parentheses etc, as I did above. Mughal states that prefix increment operators associate right to left and postfix operators associate left to right (how would you do that association?).
In the example above the "++" operator is being applied concurrently with the variable evaluation, and this is the crux of the matter. Applying the operators must be a distinct step unless the associativity rules applying to unary operators are absolutely meaningless.
Here's the answer I'm going to use to allow myself to sleep tonight :

1) (x++)-(x++) * (x++);
2) (x++)- ((x++) * (x++)); // "*" has higher precedence
3) (((x++)) - ((x++) * (x++))); //JLS 15.7.1: "Evaluate Left-Hand Operand First.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated"
But this doesn't explain how the prefix and postfix operators have different orders of associativity. I guess some things mortals are not meant to know....
[This message has been edited by herb slocomb (edited March 10, 2001).]
[This message has been edited by herb slocomb (edited March 10, 2001).]
[This message has been edited by herb slocomb (edited March 10, 2001).]
[This message has been edited by herb slocomb (edited March 10, 2001).]
[This message has been edited by herb slocomb (edited March 10, 2001).]
[This message has been edited by herb slocomb (edited March 10, 2001).]
[This message has been edited by herb slocomb (edited March 10, 2001).]
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4442
    
    5

Herb,
First of all, please don't take anything I write in this post the wrong way. I understand that you just want to understand a fundamental concept.
But let me ask you this: What would you do if you ran into obfuscated code like this in real life? Would you really lose sleep over it? Would you spend more than 5 minutes debating with your fellow programmers over which operator was associated with which operand and why you were getting the results you were getting? Or would you just say, "Hey, I know what results I want and this is how I would get it..." and proceed to write clear and unambiguous code? IMHO, there's no point in beating yourself up over some code that you probably won't encounter too often and which you'll probably end up re-writing anyway.
There are far too many more interesting and useful things to learn about Java. And don't worry that this type of question will come out in the certification exam because it most probably won't (at least I didn't have any in mine). If it did, I would think less of the exam writers than I would of you if you answered it incorrectly (not that I think you really care about my opinion of you ). Just my $0.02.
As for an example, I don't know if this is what you're looking for but it's the best I could do in under 1 minute:
int i = 1;
int j = -++i;
System.out.println("i = " + i + "; j = " + j);
i = 1;
j = -i++;
System.out.println("i = " + i + "; j = " + j);
Output is:
i = 2; j = -2
i = 2; j = -1
J.Lacar

Originally posted by herb slocomb:

Here's the answer I'm going to use to allow myself to sleep tonight :
1) (x++)-(x++) * (x++);
2) (x++)- ((x++) * (x++)); // "*" has higher precedence
3) (((x++)) - ((x++) * (x++))); //JLS 15.7.1: "Evaluate Left-Hand Operand First.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated"
But this doesn't explain how the prefix and postfix operators have different orders of associativity. I guess some things mortals are not meant to know....


[This message has been edited by JUNILU LACAR (edited March 10, 2001).]


Junilu - [How to Ask Questions] [How to Answer Questions]
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: simple operator precedence question
 
Similar Threads
who can tell me why?
postfix and prefix increment precedence in conditional expressions
unary operator
Oder of precedence???
simple array assignment question