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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
• Campbell Ritchie
• Devaka Cooray
• Ron McLeod
• Paul Clapham
• Liutauras Vilda
Sheriffs:
• paul wheaton
• Jeanne Boyarsky
• Tim Cooke
Saloon Keepers:
• Stephan van Hulst
• Tim Holloway
• Tim Moores
• Mikalai Zaikin
• Carey Brown
Bartenders:

# logical operator precedence

Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:
Had a rather unwelcome break from studying, courtesy of two broken elbow, so forgive me if I'm a little rusty/have confused myself.......

But:

If && has greater precedence than || I assume that these statements are equivalent:

Correct? (I double checked in Horstmann's core java 3.5.7)

But then why does:

What am I missing? I don't think it's the non-short circuit operator, or the additional brackets in the second example.....

To be honest I can see the logic behind both approaches, but I can't understand both being correct. I know I'm being thick, but....!

Regards,

Nick

Bartender
Posts: 3648
16
• 1
• Number of slices to send:
Optional 'thank-you' note:
Hello

There are || (logical OR), && (logical AND), & (bitwise AND), | (bitwise OR), ^ (bitwise XOR) operators.

The bitwise operators &, ^ and | operators (in order) have higher precedence than && and ||.

Therefore
a && b || c is same as (a && b) || c
a && b | c is same as a && (b | c)
a & b | c is same as (a & b) | c
a || b && c is same as a || (b && c)
a && b & c is same as a && (b & c)
a | b && c is same as (a | b) && c
a | b || c ^ d && e & f will become (a | b) || [(c ^ d) && (e & f)]

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:
Thanks a lot!

I'm surprised that I missed that in my studies so far.

Regards,

Nick

Ranch Hand
Posts: 789
• Number of slices to send:
Optional 'thank-you' note:
I figured it was left to right with logical operators for a long time, until I realized there was a precedence. It's especially worth remembering that = has the lowest precedence of all. How'd you break both elbows? You must be a man of action

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:

Guillermo Ishi wrote:I figured it was left to right with logical operators for a long time, until I realized there was a precedence. It's especially worth remembering that = has the lowest precedence of all. How'd you break both elbows? You must be a man of action

haha, no, just got clipped by a van whilst on my bike and went over the handlebars. very painful for the first two weeks, but i've got pretty decent movement back now. lucky i guess.

Anyway, I'm just surprised that | doesn't have the same precedence as ||. Learn something new everyday

Nick

Sheriff
Posts: 11604
178
• Number of slices to send:
Optional 'thank-you' note:

K. Tsang wrote:a && b | c is same as a && (b | c)

That's wrong! Operators are evaluated from left to right. So there's no way b and c will be evaluated before a. If that would have been the case, then && would not be a short-circuit operator anymore!!!

I have put together some nice little program (for another thread about the same topic, so it's definitely worth reading that one as well). This program is useful in this thread as well to experiment yourself using different operators and boolean values.

First using && and || operators:Output:
(b1) b1:false b2:false b3:false
(b2) b1:true b2:false b3:false
b1:true b2:true b3:false result:true

So evaluation from left to right (that's why b1 is evaluated first). b3 is not evaluated, because || is a short-circuit operator.

A second example using && and | operators:Output:
(b1) b1:false b2:false b3:false
(b2) b1:true b2:false b3:false
(b3) b1:true b2:true b3:false
b1:true b2:true b3:true result:true

So again evaluation from left to right (that's why b1 is evaluated first). This time b3 is evaluated as well, because | is not a short-circuit operator.

And finally a third example using the same operators, but now b1 evaluates to falseOutput:
(b1) b1:false b2:false b3:false
b1:false b2:false b3:false result:false

Only b1 is evaluated, because evaluation happens from left to right. And because && is a short-circuit operator, b2 and b3 are not evaluated.

Hope it helps!
Kind regards,
Roel

Guillermo Ishi
Ranch Hand
Posts: 789
• Number of slices to send:
Optional 'thank-you' note:
For the sake of simplicity, how would you rewrite K. Tsang's table?

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:
wow, I'm definitely going to go through all that, thanks Roel.

it seems like, even though they are evaluated left to right (so i understand a is first), that it still behaves like a && (b | c) rather than (a && b) | c

hard to explain - i guess that precedence is therefore not quite the same as evaluation order....

K. Tsang
Bartender
Posts: 3648
16
• Number of slices to send:
Optional 'thank-you' note:
Hmm I disagree.

Looking at a && b | c first. If short circuited, the b | c will not be evaluated right? If this holds as long as "a" is true, the output will be true. BUT

Similar rationale for a && b & c.

Roel De Nijs
Sheriff
Posts: 11604
178
• 1
• Number of slices to send:
Optional 'thank-you' note:

K. Tsang wrote:Hmm I disagree.

Looking at a && b | c first. If short circuited, the b | c will not be evaluated right? If this holds as long as "a" is true, the output will be true.

Why If a is true, b | c will be evaluated, because the short-circuit AND operator will only result in true if both operands are true. So if the left operand evaluates to true, the right operand will be evaluated (and determine the outcome). If the left operand evaluates to false, then the right operand won't be evaluated (because it can never be true). In your example b | c evaluates to false, so that's why false is printed.

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:

K. Tsang wrote:Hmm I disagree.

Looking at a && b | c first. If short circuited, the b | c will not be evaluated right? If this holds as long as "a" is true, the output will be true. BUT

but that doesn't mean it evaluates (b | c) first, does it? it just means it has evaluated that part because && requires it.

so if it was false && true | true, b and c would be false (if initially default values)

i think......

K. Tsang
Bartender
Posts: 3648
16
• Number of slices to send:
Optional 'thank-you' note:

Roel De Nijs wrote:

K. Tsang wrote:Hmm I disagree.

Looking at a && b | c first. If short circuited, the b | c will not be evaluated right? If this holds as long as "a" is true, the output will be true.

Why If a is true, b | c will be evaluated, because the short-circuit AND operator will only result in true if both operands are true. So if the left operand evaluates to true, the right operand will be evaluated (and determine the outcome). If the left operand evaluates to false, then the right operand won't be evaluated (because it can never be true). In your example b | c evaluates to false, so that's why false is printed.

Right Roel, I was figuring/ checking when does the right operand gets evaluated.

expr1 && expr2 represents a logical AND operation that employs short-circuiting behavior. That is, expr2 is not evaluated if expr1 is logical 0 (false). Each expression must evaluate to a scalar logical result.

expr1 || expr2 represents a logical OR operation that employs short-circuiting behavior. That is, expr2 is not evaluated if expr1 is logical 1 (true). Each expression must evaluate to a scalar logical result.

Roel De Nijs
Sheriff
Posts: 11604
178
• Number of slices to send:
Optional 'thank-you' note:

nick woodward wrote:but that doesn't mean it evaluates (b | c) first, does it? it just means it has evaluated that part because && requires it.

Exactly!

nick woodward wrote:so if it was false && true | true, b and c would be false (if initially default values)

If it wasthen false would be printed, and true | true would never be evaluated (because && is a short-circuit operator and if the left operand is false, the right operand will never be evaluated because the result will always be false).

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:
yeah, sorry i meant if it was

a = false && b = true | c = true;

but yeah, I think I'm on the right page. that link you provided is decent, thanks.

is it just me, or is there not a huge amount of discussion (in text books) of this distinction between precedence and evaluation order when using these operators?

it appears that a && (b | c) IS correct for precedence, but that evaluation order trumps precedence. however it is still not the same as (a && b) | c. I'm going to look at your program (above) to see if this becomes a bit clearer.

i think if i ever had to translate a real world problem and differentiate between the two I'd shoot myself :P

------------- edit:

I know everyone is different, but to be honest for me this does not help make things clearer at all, however the rest of that thread is great, and in fact you explain very similar code very well in your post starting "it's hard, very hard". I'm now getting all the examples correct

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:

Guillermo Ishi wrote:For the sake of simplicity, how would you rewrite K. Tsang's table?

Thought I'd try and answer this:- I'm not sure you easily can!

For example:

a && b | c does have the precedence a && (b | c) - but that isn't useful because it implies you work out (b | c) first, which isn't correct because the order of evaluation trumps the precedence.

so i guess the easiest way to write the answer would be:

if(a){ b | c };

I'm no doubt wrong/that's a bad way to represent it, but that is so far my understanding!

Roel De Nijs
Sheriff
Posts: 11604
178
• Number of slices to send:
Optional 'thank-you' note:

nick woodward wrote:yeah, sorry i meant if it was

a = false && b = true | c = true;

but yeah, I think I'm on the right page. that link you provided is decent, thanks.

Spot-on! (Of course if all three variables have false as initial value )

nick woodward wrote:is it just me, or is there not a huge amount of discussion (in text books) of this distinction between precedence and evaluation order when using these operators?

I agree! But that's probably mainly because I can't remember to have encountered questions like this on the exam which have more than one logical operator in the same statement. So these topics go way beyond what you need to know for the exam.

nick woodward wrote:I know everyone is different, but to be honest for me this does not help make things clearer at all, however the rest of that thread is great, and in fact you explain very similar code very well in your post starting "it's hard, very hard". I'm now getting all the examples correct

Don't get overwhelmed by this code snippet. It looks crazy at first glance (and maybe even at second and third glance as well ), but it's really very handy to see how expressions are evaluated. Normally the code snippet would beBut now you know only the values of every variable and the result, not the execution order. So to be able to determine the execution order, I created the additional b() method: it takes an index (to know which b variable is processed, the three variables (b1, b2, b3) and the value (b) you want to assign to that particular b? variable. So if you look at the original code snippet you havewhich becomesAnd exactly for the other expressions (only the index will change). Now let's assume you want to test what happens if you assign false to b2, then the only thing you need to do is: change (b2 = b(2, b1, b2, b3, true)) to (b2 = b(2, b1, b2, b3, false)). That's it!

nick woodward wrote:it appears that a && (b | c) IS correct for precedence, but that evaluation order trumps precedence. however it is still not the same as (a && b) | c. I'm going to look at your program (above) to see if this becomes a bit clearer.

Let's use the same statement and try 3 different scenarios: one without parantheses, one with parantheses around && and finally one with parantheses around ||. Then you can compare the different outputs and see if adding parantheses matters. Fasten your seatbelt! Here we go!

1. (b1 = false) && (b2 = true) || (b3 = true) (without parantheses)
Output:
(b1) b1:false b2:false b3:false
(b3) b1:false b2:false b3:false
b1:false b2:false b3:true result:true

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

3. (b1 = false) && ((b2 = true) || (b3 = true)) (parantheses around ||)
Output:
(b1) b1:false b2:false b3:false
b1:false b2:false b3:false result:false

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

Now because we are really having so much fun here let's do the same with using && and | operators.

1. (b1 = false) && (b2 = true) | (b3 = true) (without parantheses)
Output:
(b1) b1:false b2:false b3:false
b1:false b2:false b3:false result:false

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

3. (b1 = false) && ((b2 = true) | (b3 = true)) (parantheses around |)
Output:
(b1) b1:false b2:false b3:false
b1:false b2:false b3:false result:false

Conclusion: So again adding parantheses matters. And (b1 = false) && (b2 = true) | (b3 = true) is equivalent to (b1 = false) && ((b2 = true) | (b3 = true)) (which is different from using && and || operators).

Hope it helps!
Kind regards,
Roel

Roel De Nijs
Sheriff
Posts: 11604
178
• Number of slices to send:
Optional 'thank-you' note:

nick woodward wrote:a && b | c does have the precedence a && (b | c) - but that isn't useful because it implies you work out (b | c) first, which isn't correct because the order of evaluation trumps the precedence.

That's spot-on! (It's illustrated in my previous post).

nick woodward wrote:so i guess the easiest way to write the answer would be:

if(a){ b | c };

To keep things simple, I would just stick with a && b | c and a && (b | c), but clearly mention (at the start of the table for example) that these parantheses don't denote execution order. So in a && (b | c), a will still be evaluated first.

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:
cheers!

I knew the results of all of your examples quickly before looking at your answers thanks to that previous thread, so I definitely understand now!

And ok, by the looks of things your program is also printing the initial values of the booleans along with the result of the expression? fair enough!

honestly, this website is invaluable - it's amazing how these topics often appear so simple and are described as such in the literature (less so in the certification books to be fair), but end up being quite complex. there are several topics I feel really quite strong on now, and it's largely down to this place, and in particular your posts roel! appreciated!

have you ever considered a 'best of' thread? for example combining links to the threads you usually point posters to?

regards,

nick

Roel De Nijs
Sheriff
Posts: 11604
178
• Number of slices to send:
Optional 'thank-you' note:

nick woodward wrote:I knew the results of all of your examples quickly before looking at your answers thanks to that previous thread, so I definitely understand now!

That's awesome to hear!

nick woodward wrote:And ok, by the looks of things your program is also printing the initial values of the booleans along with the result of the expression? fair enough!

It's not really the original value (as that would always be false and thus quite useless). But it prints the current value of the booleans when the expression is evaluated.

nick woodward wrote:honestly, this website is invaluable - it's amazing how these topics often appear so simple and are described as such in the literature (less so in the certification books to be fair), but end up being quite complex. there are several topics I feel really quite strong on now, and it's largely down to this place, and in particular your posts roel! appreciated!

Thanks for these kind words. Highly appreciated!

nick woodward wrote:have you ever considered a 'best of' thread? for example combining links to the threads you usually point posters to?

That's something I haven't considered yet. Probably because I think only a few links will be in this "best of" thread. But could definitely be something to think about in the (near) future (when I have created a bunch other quality posts).

nick woodward
Ranch Hand
Posts: 386
12
• Number of slices to send:
Optional 'thank-you' note:
No worries! - You put a lot of work in.

Roel De Nijs wrote:
That's something I haven't considered yet. Probably because I think only a few links will be in this "best of" thread. But could definitely be something to think about in the (near) future (when I have created a bunch other quality posts).

Yeah, it was just a thought I had when looking at the detail some of your posts go in to, examples and all. Seemed a shame to have them spread (not so) thinly across multiple threads, and might also make linking people to answers a bit easier in the future.

Anyway, as always, appreciated!

Nick

 And when my army is complete, I will rule the world! But, for now, I'm going to be happy with this tiny ad: a bit of art, as a gift, that will fit in a stocking https://gardener-gift.com