Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

logical operator precedence

 
nick woodward
Ranch Hand
Posts: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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




 
K. Tsang
Bartender
Posts: 3585
16
Android Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot!

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

Regards,

Nick
 
Guillermo Ishi
Ranch Hand
Posts: 789
C++ Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
C++ Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For the sake of simplicity, how would you rewrite K. Tsang's table?
 
nick woodward
Ranch Hand
Posts: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 3585
16
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 3585
16
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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


 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic