Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!

# Evaluating a boolean expression with assignments and short circuit operators

Daniel Clinton
Ranch Hand
Posts: 46
5
• 1
This evaluation of this code is not clear to me

The && has higher precedence than the ||
Is it just simply Left to Right evaluation that brings about the short circuit with only b1 assigned?

Sergej Smoljanov
Ranch Hand
Posts: 467
10
i think it eluvated from left to right and groped expression like:

and like this it become:

Is it just simply Left to Right evaluation that brings about the short circuit with only b1 assigned?

Yes

Roel De Nijs
Sheriff
Posts: 10662
144
• 1
2 things play along here:
• short circuit operators: the second operand is evaluated only if needed (no valuable CPU cycles are wasted if the result is already obvious after evaluating the first operand)
• operators are evaluated from left to right, except for assignment operators (which are evaluated right to left)

• So this is what happens:
• in order to assign a value to result the right operand ((b1 = true) || (b2 = true) && (b3 = true) is evaluated
• the expression (b1 = true) || (b2 = true) && (b3 = true) is evaluated from left to right, so (b1 = true) is evaluated first and returns (obviously) true
• the following operator is the short-circuit OR operator ||, because the left operand (b1 = true) is true, the result will always be true no matter what the result of the right operand (b2 = true) && (b3 = true) is, therefore it's not evaluated at all

• Hope it helps!

Sergei Zhylinski
Ranch Hand
Posts: 84
1
• 1
Hi,

But nevertheless, I don't understand... Another example:

The result of the preceeding code is 30. Assignment operators have the same precedence. We have two assignments operators, so we should execute them as per their associativity, i.e. from right to left. The first operator that is to be executed is '*='. Its result is 20. But then the other assignment operator '+=' adds 10 to 20. Why doesn't it add 20 to 20? The '*=', when have been executed first, must have been assigned a new value to the variable, mustn't it?

One more code sample:

Roel De Nijs
Sheriff
Posts: 10662
144
• 3
For both your examples the same rule applies: operators are evaluated from left to right, except for assignment operators (which are evaluated right to left)

This is an assignment operator, so it's evaluated from right to left; meaning 10 is assigned to variable i.

A simple example:

The first 2 lines are exactly the same as the really simple example. The 3rd line is also an assignment: a value will be assigned to variable k. To know the actual value, we'll need to evaluate the right expression i + j. This expression is evaluated from left to right, so 10 + 20 is evaluated to 30 and 30 is assigned to variable k.

Now it's time to take a look at your second example:

The 1st line is exactly the same as the really simple example. The 2nd line is similar to the 3rd line from the simple example. So in order to know which value will be assigned to i, we have to evaluate the right expression from left to right i + ++i. So here we go:
• step 0: i + ++i
• step 1: 10 + ++i (replace i with its current value 10)
• step 2: 10 + 11 (increment actual value from i with 1, assign this value to i and use this value in the expression; this new value of i will only be used for next occurences of i, not for previous ones, because these were already evaluated)
• step 3: 21 (execute the addition)

• Now we know which value (21) can be assigned to variable i.

Now let's swap the 1st and 2nd operand of the assignment and see if there is a difference in the output.

Only the steps differ from the previous example, so here we go again:
• step 0: ++i + i
• step 1: 11 + i (increment actual value from i with 1, assign this value to i and use this value in the expression; this new value of i will only be used for next occurences of i, not for previous ones, because these were already evaluated)
• step 2: 11 + 11 (replace i with its current value 11, not 10)
• step 3: 22 (execute the addition)

• So 22 is assigned to variable i and the order of operands in this example does really matter!

Now let's see if you can work out your other example yourself:

Hope it helps!

Henry Wong
author
Marshal
Posts: 22119
88
• 2
Sergey Zhylinsky wrote:I don't understand... Another example:

The result of the preceeding code is 30. Assignment operators have the same precedence. We have two assignments operators, so we should execute them as per their associativity, i.e. from right to left. The first operator that is to be executed is '*='. Its result is 20. But then the other assignment operator '+=' adds 10 to 20. Why doesn't it add 20 to 20? The '*=', when have been executed first, must have been assigned a new value to the variable, mustn't it?

No. Order of evaluation, precedence, and associativity are three different concepts. You are right in that the precedence does not apply here, but the order of evaluation is still left to right. In other words, you have to apply the associativy from right to left, but evaluate it from left to right...

The best way to do that is ... think of this...

as

Now, you have to go from left to right, but have to use temporary variables as you need to complete the right assignment first. In other words, the left assignment will actually be started first, as the evaluation is going left to right, but the right assignment would be completed first, due to right to left associativity.

Henry

Sergei Zhylinski
Ranch Hand
Posts: 84
1
Hi,

Now I begin to understand the code:

The precedence of '&&' is higher than that of '||'. Therefore, it would be executed first. But order of evaluation is beyond the precedence and associativity. As the evaluation order comes from left to right, the first expression '(b1 = true)' will be evaluated first. As it is 'true' there is no need to evaluate other expressions.

Roel De Nijs
Sheriff
Posts: 10662
144
Sergey Zhylinsky wrote:The precedence of '&&' is higher than that of '||'. Therefore, it would be executed first. But order of evaluation is beyond the precedence and associativity. As the evaluation order comes from left to right, the first expression '(b1 = true)' will be evaluated first. As it is 'true' there is no need to evaluate other expressions.

Exactly!

Now what will the output be if || and && are swapped? What's the output of this code snippet?

Sergei Zhylinski
Ranch Hand
Posts: 84
1
• 1
Roel De Nijs wrote:
Sergey Zhylinsky wrote:The precedence of '&&' is higher than that of '||'. Therefore, it would be executed first. But order of evaluation is beyond the precedence and associativity. As the evaluation order comes from left to right, the first expression '(b1 = true)' will be evaluated first. As it is 'true' there is no need to evaluate other expressions.

Exactly!

Now what will the output be if || and && are swapped? What's the output of this code snippet?

So the expression

Can be explicitely decomposed into subexpressions by providing parentheses as per operators' precedence and associativity:

Hence, there are two general subexpressions:

and

The evaluation begins from left to right, so the first expression that is to be evaluated is:

The 'b1' and 'b2' vars will be assigned to 'true'.

As this expression equals to 'true', and the operator '||' is short-circuit, there is no need to evaluate the second expression:

So the result would be: b1:true b2:true b3:false result:true

Roel De Nijs
Sheriff
Posts: 10662
144
Sergey Zhylinsky wrote:So the result would be: b1:true b2:true b3:false result:true

You are spot-on!

Tony Singarayar
Greenhorn
Posts: 13
Hi,
I have a doubt in sergei's last reply...

Wouldn't line 3 be evaluated as per below.
1.(b1 = true) &&( (b2 = true) || (b3 = true))
OR
2.((b1 = true) && (b2 = true)) || (b3 = true); //as sergei mentioned...
In both the cases answer is true thou.
Thanks,
Tony Singarayar

Roel De Nijs
Sheriff
Posts: 10662
144
Tony Singarayar wrote:Wouldn't line 3 be evaluated as per below.
1.(b1 = true) &&( (b2 = true) || (b3 = true))
OR
2.((b1 = true) && (b2 = true)) || (b3 = true); //as sergei mentioned...

This example shows that when you use both && and || operators in 1 statement you should use parantheses to increase readibility & maintainability. But that advice would not be of any help on the actual exam

Because the && operator has higher precedence than the || operator, I have to go for option 2 (like Sergei mentioned)

Tony Singarayar
Greenhorn
Posts: 13
Roel,
Please correct me where my understanding has gone wrong.

1.If the expression's operands doesn't have brackets, the expression is evaluated based on precedence of operator.
2.If the expression involves brackets(if one of the operand has brackets), evaluation is done from left to right only.
3. Which means that first operand is evaluated first and then its operated with remaining expression. Operator precedence doesn't come into play here...

If the above 3 points are true, Operation sequence of below code is....

1.true&&(b2 = true) || (b3 = true)
2.true&&true||(b3=true)
3.true||(b3=true)
4.returns true even thou (b3=true) is not evaluated.

Thanks,
Tony Singarayar

Roel De Nijs
Sheriff
Posts: 10662
144
• 4
Tony Singarayar wrote:1.If the expression's operands doesn't have brackets, the expression is evaluated based on precedence of operator.
2.If the expression involves brackets(if one of the operand has brackets), evaluation is done from left to right only.
3. Which means that first operand is evaluated first and then its operated with remaining expression. Operator precedence doesn't come into play here...

That's not 100% correct.

Let's use a few simple examples to explain the rules.

1. Operators with higher precedence are evaluated before operators with relatively lower precedence.

* has higher precedence than -, so 7 is evalauted first, then 4 * 2 is evaluated and finally 7 - 8 is evaluated.

2. When operators of equal precedence appear in the same expression, evaluation from left to right (except assignment operators which are evaluated right to left).

+ has same precedence than -, so 7 - 4 is evaluated first and then 3 + 2 is evaluated. (If evaluation was from right to left, the result would be 1; first 4 + 2, then 7 - 6)

3. Operator precedence can be overridden by using round brackets (parantheses)

Because of the parantheses, 7 - 4 is evaluated first and then 3 * 2 is evaluated.

So no parantheses in your example (b1 = true) && (b2 = true) || (b3 = true), so the expression is evaluated from left to right.

If you want to know in which order each part is executed you can add some helper methods. Using the following code you could also very easily change the return value and see its effect on which parts of the expression are evaluated.

Hope it helps!
Kind regards,
Roel

Tony Singarayar
Greenhorn
Posts: 13
Thank You So much Roel!!!
Thanks for the detailed and stepwise answer.
That explains it all!!!
Tony Singarayar.

Tony Singarayar
Greenhorn
Posts: 13
Roel,
I pondered over your answer yesterday...I have few more queries.In the code below,

Since parentheses are takes priority over operator precedence, should parantheses-assignment((b1 = true),(b2 = true),(b3 = true)) be happening first.
The evaluation would simply become true && true|| true and result will be true aswell.
Please let me know whether to start a new topic.

Thanks,
Tony Singarayar

Roel De Nijs
Sheriff
Posts: 10662
144
• 1
Tony Singarayar wrote:Since parentheses are takes priority over operator precedence, should parantheses-assignment((b1 = true),(b2 = true),(b3 = true)) be happening first.

No, it doesn't work that way. Evaluation is still left to right. If parantheses would be always evaluated first, short-circuit operators would not exist (as shown in your example).

In this example, first the 2 is evaluated (and not 3 + 5), then 3 + 5 is evaluated and finally 2 * 8.

This produces no output, but also no runtime exception:

I can add as many parantheses as I want, but these have no effect at all. This code snippet and the previous one are exactly the same:

And what happens if we replace the short-circuit && with &?

So evaluation is left to right, but you can override operator precedence using parantheses. But not all expressions in parantheses are evaluated first.

Evaluation in this order: 1+2, 3+3, 6+4, 10+5 and 15+6

This one is NOT evaluated in this order: 1+2, 3+4, 5+6, 3+7 and 10+11
but is evaluated in this order: 1+2, 3+4, 3+7, 5+6 and 10+11

Hope it helps!

Prathima gaitonde
Ranch Hand
Posts: 130
3
I think I am getting it in bits and pieces but not fully, Sorry for not grasping it or missing the bits here,

What does associativity means?

What is its order out of 3

a>Order of evaluation
b>Order of precedence

and c>Associativity?

Thanks, for the help
Prathima

Roel De Nijs
Sheriff
Posts: 10662
144
• 1
Prathima gaitonde wrote:What does associativity means?

What is its order out of 3

a>Order of evaluation
b>Order of precedence
and c>Associativity?

• Precedence order: When 2 operators share an operand the operator with the higher precedence goes first. Little example: 2 + 3 * 4 is treated as 2 + (3 * 4) (as multiplification has higher precedence than addition)
• Associativity: When an expression has 2 operators with the same precedence, the expression is evaluated according to its associativity. Another little example: 12 - 6 - 6 can be treated as (12 - 6) - 6 or 12 - (6 - 6). And it's important to know as both results are different (0 or 12). The subtraction has left-to-right associativity, so 12 - 6 - 6 is treated as (12 - 6) - 6.
• Order of evaluation of (sub)expressions: In Java (sub)expressions are evaluated from left to right.
• Short circuiting: When using the conditional && and || operators, Java does not evaluate the 2nd operand unless it is necessary to resolve the result.

• Let's take the 1st example from the original post again:

Order of evaluation is left-to-right, so we start with (b1 = true). This evaluates to true. Because the || operator is used, there is no need to evaluate the right side of the operator, because the left side is true, the result will always be true. So the right side of the || operator will never be evaluated. That's why the result is: b1:true b2:false b3:false result:true

Now let's see if you have understood and you can work out the following exercise itself. I made a small modification to the previous example. How is the 2nd line evaluated and what's the output?

Hope it helps!
Kind regards,
Roel

Prathima gaitonde
Ranch Hand
Posts: 130
3

My understanding,

1> Here in the above code associativity has no meaning as the operator && has higher precedence than operator ||.

2> Evaluation begins from left to right, Hence (((b1=true)&&(b2=true)) || (b3=true)), here b1=true first innermost bracket from left is evaluated then there is && operator, which is a short circuit, so as the b1=true it has to check for the value of b2 which is then assigned a value true. Now second innermost bracket from left results true, next operator is || as this short circuit operator looks for value true in the first place it wont evaluate value of b3, hence result is assigned a value true.

Hence final out put is b1=true, b2=true, b3=false, result=true.

Correct me if I am wrong.

@Roel De Nijs Thanks, for your patience and detailed explanation.....

Roel De Nijs
Sheriff
Posts: 10662
144
• 1
Prathima gaitonde wrote:Hence final out put is b1=true, b2=true, b3=false, result=true.

Correct me if I am wrong.

No need to correct you, your explanation (and final result) are spot-on

I only wonder why you added parantheses in the statement, because as you know: you can change the order of execution by adding parantheses. But luckily you added them on the right place So the original version (b1 = true) && (b2 = true) || (b3 = true) and your adapted version (((b1=true) && (b2=true)) || (b3=true)) are evaluated in exactly the same way

Sharmili Rameshbabu
Greenhorn
Posts: 27
2
Prathima gaitonde wrote:
2> Evaluation begins from left to right, Hence (((b1=true)&&(b2=true)) || (b3=true)), here b1=true first innermost bracket from left is evaluated then there is && operator, which is a short circuit, so as the b1=true it has to check for the value of b2 which is then assigned a value true. Now second innermost bracket from left results true, next operator is || as this short circuit operator looks for value true in the first place it wont evaluate value of b3, hence result is assigned a value true.

Hence final out put is b1=true, b2=true, b3=false, result=true.

I went through the entire discussion, still i dont understand one point that why should the evaluation actually happening is (((b1=true)&&(b2=true)) || (b3=true)), instead of (b1=true)&&((b2=true) || (b3=true))

In the second form also. && is given higher precedence and rest of the expression is considered as the second operand. Please advise

And which is given more priority, Precedence or Associativity? Because in the first example,(b1=true)||(b2=true) && (b3=true) , Associativity was considered. In the second one, (b1=true)&&(b2=true) || (b3=true) , Precedence is considered.

Many thanks

Roel De Nijs
Sheriff
Posts: 10662
144
• 1
Sharmili Rameshbabu wrote:I went through the entire discussion, still i dont understand one point that why should the evaluation actually happening is (((b1=true)&&(b2=true)) || (b3=true)), instead of (b1=true)&&((b2=true) || (b3=true))

In the second form also. && is given higher precedence and rest of the expression is considered as the second operand. Please advise

It's hard, very hard! So still being confused is not a big deal. Many seasoned java developers would struggle with these kind of questions. And I have to say: I didn't encounter such hard questions on the OCAJP7 exam.

According to the operator precedence page we know logical AND (&&) has a slightly higher precedence than logical OR (||). So that's why it makes sense to think, the expression is evaluated like ((b1=true) && (b2=true)) || (b3=true). But in this statement parentheses don't make any difference, the output is always the same. Illustrated with this code snippet:

Every method will print the same line, so you'll get (if you run the program):
b1:true b2:true b3:false result:true
b1:true b2:true b3:false result:true
b1:true b2:true b3:false result:true

It gets more interesting when we switch the logical operators, as in the following code snippet:

When you run this program, you'll get the following output:
b1:true b2:false b3:false result:true
b1:true b2:false b3:true result:true
b1:true b2:false b3:false result:true

As you can see, method1 and method3 have the same output, method2 has a different one. method1 doesn't have parantheses to override the order of execution like in method2 and method3. In method2 you'll have parantheses around the logical OR, in method3 the logical AND is put in between parantheses. So if you put parantheses around the logical OR (method2) you'll get a different output, so you have another evaluation of your expression (because of the use of parantheses).

And as a bonus I'll add this code example (very similar to the 1st code snippet):

When you run this program, you'll get the following output:
b1:false b2:false b3:true result:true
b1:false b2:false b3:true result:true
b1:false b2:false b3:false result:false

Now the output of method1 and method2 is exactly the same and method3 is different. So that means method1 and method2 define the same evaluation of your expression. In method3 you have another evaluation (because of the use of parantheses). And to end this post: method1 and method2 are equivalent to (((b1=true)&&(b2=true)) || (b3=true)) and method3 is equivalent to (b1=true)&&((b2=true) || (b3=true)). As proven by the output, the 1st one is the correct evaluation.

Hope it helps!
Kind regards,
Roel

Sharmili Rameshbabu
Greenhorn
Posts: 27
2
Hi Roel,

Thanks for the reply with lot of experiments, i read your reply several times and I did a small research over few other possibilities like

and able to predict the order of evaluation, having said that these type of questions are rare in the exam, am not going to spend more time on this.

And a small request, Can you please reply to my post here

With Regards
Sharmili

Roel De Nijs
Sheriff
Posts: 10662
144
Sharmili Rameshbabu wrote:And a small request, Can you please reply to my post here

No worries, it's still on my to do list to have a look and reply Please don't forget we are all volunteers here, so we have to do other things to get our bills paid in time.

Sharmili Rameshbabu
Greenhorn
Posts: 27
2
Sorry about that Roel! I completely understand and you guys are really doing an amazing job. I just assumed that my post was missed, that is the reason i reminded about it.

Sachin Tripathi
Ranch Hand
Posts: 368
3
Hello Roel
Let me sum up things(considering op's first post)

1-&& has higher precedence than ||

2-so left to right executions begins

b2=true
&& doesn't get Short circuited
b3=true
true&&true=true

Now || has to be evaluated

(b1=true)||true

|| gets short circuited

Final result:

b1=false;b2=b3=result= true;

Where I am deviating from correct path,would love if you will point the exact step

Henry Wong
author
Marshal
Posts: 22119
88
• 1
Sachin Tripathi wrote:
Where I am deviating from correct path,would love if you will point the exact step

Precedence does not determine the order of evaluation. The expression is evaluate left to right regardless of the precedence. In terms of operators only, for this expression ...

1. The result assignment is evaluated first... but it can't be assigned until the complete RHS of the expression has completed.
2. The b1 assignment is evaluated next ... and b1 is set to true.
3. The logical OR operator is evaluated ... which short circuits the second operand.

Now... as for what is the second operand, the precedence helps determine that. Since the logical AND operator is higher in precedence than the logical OR, both the b2 and b3 portions of the expression are part of the second operand (and hence, short circuited).

Henry

Roel De Nijs
Sheriff
Posts: 10662
144
Sachin Tripathi wrote:Where I am deviating from correct path,would love if you will point the exact step

You go on the wrong path, because you don't evaluate b1 first and start immediately with the right hand side (RHS). And if you think about it, it makes no sense at all: the || operator is a short-circuit operator. Meaning if the left hand side (LHS) evaluates to true, the RHS is not evaluated at all. And you start evaluating with the RHS (which might not be evaluated at all). Like Henry already stated: expressions are evaluated from left to right, regardsless of the precedence. So b1 is evaluated first and because it's evaluated to true, the RHS of the || operator is not evaluated anymore.

Let's put that statement in my "magic" program and see if we got it spot-on. So the statementbecomes (only line4 actually matters)Output:
(b1) b1:false b2:false b3:false
b1:true b2:false b3:false result:true

So yes, we were absolutely 100% correct

Now let's see if adding parantheses would result in a different output.

1/ ((b1 = true) || (b2 = true)) && (b3 = true) (parantheses around ||)
Output:
(b1) b1:false b2:false b3:false
(b3) b1:true b2:false b3:false
b1:true b2:false b3:true result:true

2/ (b1 = true) || ((b2 = true) && (b3 = true)) (parantheses around &&)
Output:
(b1) b1:false b2:false b3:false
b1:true b2:false b3:false result:true

Conclusion: adding parantheses matters! And (b1 = true) || (b2 = true) && (b3 = true) is equivalent to (b1 = true) || ((b2 = true) && (b3 = true)).

In this thread you'll find a few other examples about the same topic and some examples are using the | operator (which is not a short-circuit operator and thus always evaluates both sides).

Hope it helps!
Kind regards,
Roel

Sachin Tripathi
Ranch Hand
Posts: 368
3
Thanks a lot
Roel and Henry

The reason behind the answer which i gave:

Output:

Evaluation = precedence(R to L)

Roel De Nijs
Sheriff
Posts: 10662
144
Sachin Tripathi wrote:Output:

Huh

The output of this code snippetis -5 (not 5)

Sachin Tripathi
Ranch Hand
Posts: 368
3
Sorry -5

@

Henry Wong
author
Marshal
Posts: 22119
88
Sachin Tripathi wrote:
The reason behind the answer which i gave:
Output:
Evaluation = precedence(R to L)

With this latest example, there aren't any operations with side effects, so evaluation order probably doesn't matter ... but ... the order of evaluation is still left to right, regardless of precedence.

So, let's look at the order of evaluation (even without any side effect concerns), just like with the example in my last post. In terms of operators only (evaluating left to right) ...

1. The c assignment is evaluated first... but it can't be assigned until the complete RHS of the expression has completed (due to precedence)
2. The subtraction operator is evaluated next ... the left operand is 7, but the right operand needs to be completed (due to precedence)
3. The multiplication operator is evaluated next ... the left operand is 4, the right operand is 3, so the result is 12

2a. The right operand completes evaluation with 12 -- and hence, the result is -5.
1a, The RHS of the expression completes evaluation with -5 -- and hence, the assignment can be completed

Again. One more time. Because I love beating a dead horse... ... Precedence and Order of Evaluation are two different things. And Order of Evaluation is left to right.

Henry

Sachin Tripathi
Ranch Hand
Posts: 368
3
I think ,now i started getting things

Evaluation always occurs from L to R

But during evaluation if operator has less precedence then following operator then the final result of operation involving less precedence operator is given after operation involving higher precedence one is given(this is general case)

But if operator has a property of short circuit and left operand compels short circuit then final result of operation involving less precedence operator can be given depending upon their position in their expression

Correct me if I m wrong

Roel De Nijs
Sheriff
Posts: 10662
144
Sachin Tripathi wrote:Evaluation always occurs from L to R

But during evaluation if operator has less precedence then following operator then the final result of operation involving less precedence operator is given after operation involving higher precedence one is given(this is general case)

Illustrated with a few examples in this post and this one.

Sachin Tripathi wrote:But if operator has a property of short circuit and left operand compels short circuit then final result of operation involving less precedence operator can be given depending upon their position in their expression

Having difficulties with understanding that statement, so it's hard to tell if you are correct or wrong.

Sachin Tripathi
Ranch Hand
Posts: 368
3
To make my point clear,consider op's first question
In which || has less precedence then &&
Even though due to short circuit property the result due to || is evaluated first without evaluating &&
Because it is the leftmost operator

Roel De Nijs
Sheriff
Posts: 10662
144
Sachin Tripathi wrote:To make my point clear,consider op's first question
In which || has less precedence then &&
Even though due to short circuit property the result due to || is evaluated first without evaluating &&
Because it is the leftmost operator

Sachin Tripathi
Ranch Hand
Posts: 368
3
1-In this || has less precedence then &&
b1=false
short circuit doesn't happen,for RHS of || ,&& has to be evaluated first(higher precedence)
b2=true
short circuit doesn't happen,
b3=true

true &&true=true
false||true=true

So b1=false b2=b3=result=true

2-In which || has less precedence then &&
b1=false
short circuit doesn't happen,for RHS of ||
b2=true(as due to presence of parenthesis, && is not evaluated)
false||true=true
b3=true
true &&true=true

So b1=false,b2=b3=result=true

Roel De Nijs
Sheriff
Posts: 10662
144
Sachin Tripathi wrote:1- So b1=false b2=b3=result=true
2- So b1=false,b2=b3=result=true

Spot on! I think you have a good understanding now of this concept.