• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
  • Knute Snortum
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Frits Walraven
Bartenders:
  • Carey Brown
  • salvin francis
  • Claude Moore

Java Operators and Precedence, Evaluation Order  RSS feed

 
Ranch Hand
Posts: 121
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Java Operators and Precedence, Evaluation Order ...

How can I correctly evaluate the following expression?



What should I use first from bellow to correctly evaluate line 7:
Precedence,
Associativity,
Evaluation Order
 
Saloon Keeper
Posts: 10136
214
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To evaluate an expression, the only important thing is order of evaluation. Precedence and associativity don't have anything to do with expression evaluation.

Precedence and associativity only come into play when building the expression tree during compilation. You can picture it as the compiler inserting explicit parentheses everywhere.

The compiler uses precedence and associativity to create the following expression tree: (((a * ((a++) - (--b))) * a) * b)

Then at runtime, order of evaluation is always left to right:

(((a * ((a++) - (--b))) * a) * b)
(((2 * ((a++) - (--b))) * a) * b)
(((2 * ((2++) - (--b))) * a) * b)
(((2 * ( 2    - (--b))) * a) * b)
(((2 * ( 2    - (--5))) * a) * b)
(((2 * ( 2    -    4 )) * a) * b)
(((2 *            -2  ) * a) * b)
((                -4    * a) * b)
((                -4    * 3) * b)
(                -12         * b)
(                -12         * 4)
                 -48
 
Marshal
Posts: 64171
215
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The correct answer is not to write expressions including the ++ and -- operators in the first place. But if you insist on doing something which should be confined to cert exam practice books, the order of evaluation is left‑to‑right. The evaluation of expressions always follows the left‑to‑right rule, even though it maintains associativity and precedence of operators. Forget about associativity because you don't have any parts of the expression where associativity makes a difference. What will make a difference is the fact that a++ hides the value of a from us; only the value of the whole expression a++ is visible at that point, and remember whether it is equal to the new or old value of a.
 
John Losty
Ranch Hand
Posts: 121
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
After this


you could go on like that as well?
 
author
Posts: 23830
140
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

John Losty wrote:
you could go on like that as well?



Actually, no. The Java specification, in this case (after respecting parens, precedence, and assoc), requires that the left operand be evaluated before the right operand. So, the "2 * ( 2    - (--5))" sub expression, must be done (started and completed) before the "a" sub expression.

Henry
 
John Losty
Ranch Hand
Posts: 121
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

in this case (after respecting parens, precedence, and assoc), requires that the left operand be evaluated before the right operand.

How do you apply it?

A post higher Stephen wrote

T o evaluate an expression, the only important thing is order of evaluation. Precedence and associativity don't have anything to do with expression evaluation.

 
Henry Wong
author
Posts: 23830
140
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

John Losty wrote:

in this case (after respecting parens, precedence, and assoc), requires that the left operand be evaluated before the right operand.

How do you apply it?



Stephen already showed you how it is done. He converted all the precedence/assoc rules into parenthesis -- so, it is easier to apply. Then, he showed you how it was done (evaluated) -- meaning the parens are used to determine the left and right operands for evaluation.

Henry
 
John Losty
Ranch Hand
Posts: 121
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't understand what he has done.
He didn't said what was applied and how, he just added this line:

The compiler uses precedence and associativity to create the following expression tree: (((a * ((a++) - (--b))) * a) * b)



Than added this:

Then at runtime, order of evaluation is always left to right: ...



also this isn't clear to me as at some point he stopped evaluating from left to right and first evaluated inside brackets.
 
Marshal
Posts: 6697
464
BSD Linux Mac OS X VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

John Losty wrote:I don't understand what he has done.
He didn't said what was applied and how, he just added this line


Read the replies carefully until all click. Stephan's showed example with hypothetical parentheses helps to re-assemble the case what is really happening behind the hood.

I'll try to repeat same stuff just in different words.

As been said by all, expressions are being evaluated from left to right. What that actually means is, each value evaluate as if there were no other values on the right, in other words, ignore them until you really need them. What I'm saying might technically isn't very accurate, but...

int a = 2;
int b = 5;
int c = a * (a++ - --b) * a * b;


1. So, initial value of 'a' is 2. So what you have is (remember, ignore the most right part from the point where you are looking at this very moment):
int c = 2 *

2. Now, in the parentheses you have a++, which means: "place the current value of 'a' in the expression and only then increment. So you have:
int c = 2 * (2
remember, after all this done, 'a' gets increment to 3.

3. So next is with b. Current value of 'b' is 5, and --b means, first decrement current b's value and only then place it into expression, so you end up with:
int c = 2 * (2 - 4)

4. Let's continue. Remember, from the step 2 you increment 'a' to 3, so now a is 3. What we have next is:
int c = 2 * (2 - 4) * 3

5. This one is similar to above, 'b' value following the step 3 ended up being 4, so:
int c = 2 * (2 - 4) * 3 * 4

So you have all unknowns revealed now. Again, looking from left to right, you do the arithmetics. Note: to a parentheses look as to a grouping, so basically they mean which operands get calculated together (formulation of mine here is perhaps wrong...).

int c = 2 * (-2) * 3 * 4
int c = -4 * 3 * 4
int c = -12 * 4
int c = -48


So if I didn't mess up anything along the way, answer would be that. Which I didn't, because Stephan also got that.
 
Marshal
Posts: 13447
222
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I believe what Stephan has shown you is the step-by-step process of evaluation. This is normally done using a stack. I don't know if you have gotten to stacks yet in your studies so just think of "evaluation" here as finding the innermost leftmost parentheses, substituting any variables inside the parentheses with their current values, calculating the term inside parentheses, then removing the parenthesis around the term. Then repeat the process starting with what's left, again finding innermost leftmost parentheses, etc., until you have reduced everything down to one term/value.

As I mentioned, this evaluation process is normally done with a stack involved and no actual parentheses. Instead, the rules of evaluation are used to turn infix expressions (where the operator is in between the operands) including explicit parentheses, into postfix expressions where the operator comes after its operands. Postfix expressions don't need parentheses to ensure correct order of evaluation.

For example, the infix expression a+b*c, evaluation is done as (a + (b * c)).

In postfix, the same expression is abc*+. The postfix (and converse prefix) order expression doesn't need parentheses around terms and subterms. This allows stack-based evaluation to be fairly straightforward.

For example, with abc*+, this is what happens if you have a = 1, b = 2, c = 3:

a: (operand)
 push a

b: (operand)
 push b

c: (operand)
 push c

*: (operator)
   pop op2 -> c
   pop op1 -> b
   substitute b = 2
   substitute c = 3
   mult 2 * 3 -> 6
   push 6

+: (operator)
   pop op2 -> 6
   pop op1 -> a
   substitute a = 1
   add 1 + 6 -> 7
   push 7

end of expression:
   pop result -> 7

When you get to the end of the postfix expression, you should have one element left on the stack which is the final result.

You can learn more about this if you search for prefix, infix, postfix notation and  stack-based processing of postfix expressions
 
Junilu Lacar
Marshal
Posts: 13447
222
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For comparison, the infix expression (a + b) * c would be ab+c* in postfix and stack-based evaluation would go something like this:

a : (operand)
   push a

b : (operand)
   push b

+ : (operator)
   pop op2 -> b
   pop op1 -> a
   substitute a -> 1
   substitute b -> 2
   add 1 +  2 -> 3
   push 3

c : (operand)
   push c

* : (operator)
   pop op2 -> c
   pop op1 -> 3
   substitute c -> 3
   mult 3 * 3 -> 9
   push 9

(End of expression):
   pop result -> 9
 
John Losty
Ranch Hand
Posts: 121
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Liutauras Vilda
I am just trying to pass the Z0-808 exam. Your post has been the most applicable for me and will stick to your suggestions.

When I stumble upon some other more difficult examples I will just ask then.

I am still not sure how difficult expressions will we have to evaluate for the exam.
 
Stephan van Hulst
Saloon Keeper
Posts: 10136
214
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Keep practicing!

Another way to interpret "left to right evaluation" in what I posted in my first reply is on every step, consider the entire expression and only evaluate the leftmost sub-expression that contains no parentheses.

So, if the sixth step looks like

the seventh step looks like

and not like

because 2 - 4 is the leftmost sub-expression that contains no more parentheses, and so is evaluated before a is evaluated.
 
Henry Wong
author
Posts: 23830
140
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

John Losty wrote:

Then at runtime, order of evaluation is always left to right: ...



also this isn't clear to me as at some point he stopped evaluating from left to right and first evaluated inside brackets.



Actually, this is not true. Others have already posted information on how to interpret the evaluation, so, I will not continue on that... except to add...

Evaluation to completion are not equal -- meaning it takes longer to complete evaluation of a longer sub expression (either with parenthesis, or added parenthesis which were done to respect precedence/associativity). When the Java specification states that the evaluation is done "left to right" (in addition to the rules on respecting precedence/assoc, parameters, etc.), it is referring to when the evaluation of the sub expression starts -- and not when it completes.

If you review Stephen's example again, and look at when the evaluation starts, you will see that he is indeed, evaluating left to right.

EDIT: Okay, in reviewing again, it may not be that easy to see. If I have time later, I will do a quick write up, and the start points, and how it is left to right.

Henry
 
it's a teeny, tiny, wafer thin ad:
Create Edit Print & Convert PDF Using Free API with Java
https://coderanch.com/wiki/703735/Create-Convert-PDF-Free-Spire
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!