This question already has answers here:
In Java, what are the boolean "order of operations"?
(6 answers)
Closed 7 years ago.
Is it logically the same to do the following:
if ( a || b || c || d)
vs
if ((a || b) || (c || d))
In other words, how does the order of the && and || operators work, left to right or right to left?
How about:
if ( a && b && c && d)
vs
if ((a && b) && (c && d))
A sequence of identical operators is evaluated left to right if left-associative, or right to left if right-associative. So for example
a || b || c
is the same as
(a || b) || c
Howver if you mix || and && then operator precedence takes over.
I would like to provide a detailed answer in order for you not only understand the Logical (AND) and (OR) but, also how the operators in general are evaluated and what are their order of precedence. There are many ways to evaluate multiple logical expressions.
The first step is to understand the truth table for OR and AND shown below (Source):
As shown above, for different values of x and y the X AND Y (X && Y) and X OR Y (X || Y) yield different values. If you pay attention below AND operation requires both X and Y to be true in order for the result to be true however in case of OR if either X or Y is true then the result is true.
You need to know the above table for AND and OR by heart.
If you wish to be able to evaluate multiple logical expressions (ANDs and ORs), De Morgen's law can help you how to do it using NOT operation.
The rules can be expressed in English as:
The negation of a conjunction is the disjunction of the negations. The
negation of a disjunction is the conjunction of the negations.
or informally as:
"not (A and B)" is the same as "(not A) or (not B)"
also,
"not (A or B)" is the same as "(not A) and (not B)".
Read more on De Morgen's law and how to evaluate multiple logical expressions using it in here and here.
Precedence of logical AND and OR are left to right. See below table (Source) and that should give you an idea which operators are right to left and which ones are left to right as well as order of their precedence for example () and [] has the highest precedence and assignments have the lowest precedence among operators. If you notice
back to your example
if ( a || b || c || d)
According to truth table there are 16 possible combinations starting from
a=true,b=true,c=true,d=true
...
...
...
a=false,b=false,c=false,d=false
As long as any of the a,b,c,d are true then outcome is true hence, out of 16 possible combinations 15 will be true and last one will be false because all a,b,c,d are false.
ON whether below is same as above? Yes.
if ((a || b) || (c || d))
The only difference between the 2 is that in the second one the brackets are evaluated first hence (a || b) is evaluated then ORd with evaluation result of (c || d) but. The same logic true for above is true here too. As long as one of a,b,c,d are true then outcome is true.
In regards to below, yes the two evaluate to same outcome.
if ( a && b && c && d)
vs
if ((a && b) && (c && d))
Same as above 16 possible combinations for different values for a,b,c,d. The only true outcome for the above is when all a,b,c,d are true. Hence only one true and another 15 false.
Both statement if ( a || b || c || d) and if ((a || b) || (c || d)) will return true if either of the variables is true.
And also statement if ( a && b && c && d) and if ((a && b) && (c && d)) will return true only if none of the variables is false.
Also evaluation is from left to right.
These are short-circuiting operators that operate left-to-right, meaning as soon as the logical value of the whole expression can't be changed by the remaining terms, execution halts. As soon as || hits a true, it stops and the whole thing is true, and as soon as && hits a false, it the whole thing is false. So even though these operators are theoretically associative and commutative, order and grouping does have a practical effect. In fact, it's common to do something like:
if (foo == null || foo.someProperty())
or
if (foo != null && foo.someProperty())
Both of these are guaranteed not to have a null pointer exception because if foo is null, the second one doesn't get evaluated.
Related
I'm trying to determine the conditions under which the following expression, where a and b are properly declared boolean variables, evaluates to false:
(a && (b || !a)) == a && b
To me, it seems that this expression will always evaluate to true. If either a or b is false, both sides of the equality operator will evaluate to false. If a and b are both true, then both sides will evaluate to true. That's all the options, and it's the correct answer for my online homework. However, when I run this in IntelliJ CE with the Java 11 JVM, it seems like it prints false whenever b is false:
when a and b are both false, IntelliJ outputs false
I get the same output when b is false and a is true. Can someone explain where the fault in my logic is? Thank you very much.
I think it is giving == operation priority over &&
Try this -
(a && (b || !a)) == (a && b)
You code should be:
boolean c = (a && (b || !a)) == (a && b);
otherwise it is evaluated as:
boolean c = ((a && (b || !a)) == a) && b;
Boolean operations have equivalent mathematical operations (this is what the CPU is ultimately doing). You can use this method to check any equation to make sure that it is coming out how you expect.
It can help you quickly see if your boolean logic is correct for all cases.
Using your equation here is an example:
Replace "true" with 1 and "false" with 0. Replace && with * (as in multiplies) and || with + (as in add). ! does what you expect still. Then check equality
so
a*(b+!a) == a*b
Then when a = false (0) and b = false(0) we have
0*(0+1) == 0*0
or 0=0
Which is true.
We can keep going with the other options to check.
a=1, b=1
1*(1+0) == 1*1
or 1=1
again, true
a=1, b=0
1*(0+1) == 1*0
1*1=0?
Not correct (false).
With that last test, we can see that this equation does not always evaluate to true. Just like in math, boolean operations have an order of operations (as mentioned by many others), but I like using this method to make sure my equations are working as intended.
Through Java operator precedence table:
'|' Logical OR operator has higher precedence than '&&' logical AND operator.
I checked above fact using following code
int y = 5;
int x = 2;
if( x++ > 2 && ++y > 2 | true )
; //do nothing
System.out.println("x = " + x + " y = " + y);
but above line giving output as -
x = 3 y = 5
showing that x++ is evaluating first.
Even I put parentheses at condition around |
if( x++ > 2 && (++y > 2 | true) )
;
But still I am getting the same output.
Why operator precedence not working in this case?
That's not the logical operator. That's the bitwise operator. It will evaluate everything - that is, it won't short circuit - and if anything flips that bit to 1, it'll stay at 1 until negated.
Here's how these statements would evaluate:
x++ > 2 && ++y > 2 || true -> true. We fail with the logical AND, but succeed with the logical OR. With short circuiting, we don't continue to evaluate any portion of the logical AND, since x > 2 is false.
x++ > 2 && (++y > 2 || true) -> false, since we will short-circut due to x > 2 not being true.
If you actually don't want the short circuit behavior, then use the bitwise AND as well, and you'll get your expected evaluation block.
x++ > 2 & ++y > 2 | true will still evaluate to true, but the values of x and y will change to 3 and 6, respectively.
| is the bitwise OR operator. You're looking for ||. It's similar, but differs in that it has higher precedence and does not apply short circuit evaluation.
I see what you're really asking now. You're wondering why if && has the least precedence, the rest of the statement isn't evaluated before finally coming to it. So in
x++ > 2 && ++y > 2 | true
it should evaluate x++ > 2, then ++y > 2 | true and finally apply &&. Well, the answer is that && applies short circuit evaluation. Sure, it can evaluation everything and then apply its effect, and that's what the bitwise operator does. However it doesn't because
if (a && b && ...)
is supposed to behave similarly to
if (a) {
if (b) {
...
}
}
Operator precedence is as you expect, however, the evaluation is terminated early because of the property of the operator. So going back to
x++ > 2 && ++y > 2 | true
We see that x++ > 2 is false, so ++y > 2 | true is not evaluated.
try this
if( x++ > 2 && ++y > 2 || true )
You are using bitwise operator not logical operator
Operators in java
Even if the operator | has higher precedence, the operator isn't even discovered at the point where the program checks if calculating the right-hand side (of &&) is necessary.
Consider the statement (true && true | true). This is how it is calculated:
Check (true && ...) to see if further operations are necessary, (which is the case).
Higher precedence: Perform the operation (true | true) -> true.
Lower precedence: Perform the operation (true && true) -> true.
In your case, since (x++ > 2) gives false, the right-hand side of && is never even touched.
Since whatever you place the braces , it will start from left to right because it in case of && , it is optimized to check first condition , it get false , then why to go to second condition , no matter braces are there ,secondly x++ will get executed , condition get false , so it is printing the same output but when you do let say using ||
class Test{
public static void main(String[] args) {
int x=2,y=5;
if( x++ > 2 || (++y > 2 | true) )
;
System.out.println(x +" "+y );
}
}
It will print 3 6 because || takes place , first condition get false but when it comes to second , ++y > 2 evaluated to true | between boolean values give output on basis of bitwise OR , true OR true is true .
The logical operators: (&& , ||, &, |, and ^) can be used only to evaluate two
boolean expressions.
The difference between && and & is that the && operator
won't bother testing the right operand if the left evaluates to false, because the
result of the && expression can never be true.
The difference between || and | is
that the || operator won't bother testing the right operand if the left evaluates to
true, because the result is already known to be true at that point.
Bitwise operators: (&, |, and ^) can also be called as "Bitwise" operators. Bitwise operators compare two variables bit by bit, and return a variable
whose bits have been set based on whether the two variables being compared had
respective bits that were either both "on" (&), one or the other "on" (|), or exactly
one "on" (^).
Is following true in java:
In java if you use || then after getting first true condition it neglects the rest conditions. That is If you write if(a || b || c) in java and java finds a is true then it will not check for b and c, just go into the if case.
Yes this is called short circuiting, if you put less expensive checks to the left you might avoid the expensive ones to follow.
This works for || and &&
one of the best uses is checking a value from an object that might be null:
if(myList != null && myList.size() > 6)
the previous line is null safe, reversing the condition will cause a null pointer exception in case myList is null
This is correct. || is called short-circuit OR evaluation, or an OR-ELSE operator.
This is important in situations when evaluating the right-hand side may cause an undesirable consequence:
if (myString == null || myString.indexOf("hello") != -1)
...
would crash if it were not for short-circuiting.
Yes, This way the compiler avoids unnecessary checking and calculation overhead.
That's correct, and that's not just laziness on part of the language implementation, but rather it is a crucial feature - short-circuiting allows you to write something like this:
if (myarray.length > 10 && myarray[10] == 5) { /* ... */ }
Here the second condition may only even be evaluated if the first one is true. Thanks to short-circuiting, if the first condition is false the second is never touched.
YES
(AFAIK)
The same things applies to && but in reverse manner.(for first false).
The same rule as in circuits for AND and OR gates.
Yes, it's called short-circuiting. It also will short circuit &&, i.e.
if (a && b && c)
If a is false then the condition cannot be true, neither b nor c are checked.
This can be problematic if you call methods that return booleans. To get around this, you can use bitwise & and |.
Yes it is correct. If you use | this operator to check OR condition then it checks rest all conditions. It also applied on AND(&) operator.
Yes, and one important thing, if you do any operations in the second part, they will not be made. For example:
int a = 5;
int b = 5;
if ( a == b || a++ == b){
...
}
//a = 5
//b = 5
BUT in case:
int a = 3;
int b = 5;
if ( a == b || a++ == b){
...
}
//a = 4
//b = 5
I tried to make a simple example, but sometimes you call a method in the second part, (which will not be called if first part was true in case of ||), or the first part was false in case of &&
(a > b) & (c < d), the components are evaluated left to right, so (a >
b) is evaluated first. If (a > b) is false, the entire expression is
false regardless of the result of the component (r < d). Nevertheless,
the component (c < d) will still be evaluated. However, in the
expression (a > b) && (c < d), the component (c < d) will not be
evaluated if (a > b) evaluates to false. This is known as short
circuiting.
Came across this paragraph in a Java book. I have been programming in various languages before, but I've never found a need for '&'. Why would one want to evaluate the second statement if it's known that the end result is not affected by it? Is there any use for it; does it come due to historical reasons?
Same question applies to | and || as well.
The && operator is defined by the Java Language Specification to perform short-circuit evaluation.
However, the & operator is not, even when applied to boolean arguments.
You could exploit this if one of the arguments had side-effects that you did not want short-circuited. However, in my experience this is uncommon, and you'd face the risk of someone "fixing" it. It would be better separated into steps. For example, instead of:
if ( foo() & bar() ) {... }
you could say:
boolean isFoo = foo();
boolean isBar = bar();
if ( isFoo && isBar ) { ... }
if you expect your code to be under attack from timing attacks you want the least amount of branches (conditional execution paths) possible, this is one way to eliminate them
The difference between '&' and '&&' is not well-known and that example from the book doesn't help much.
Here's another example to show how short-circuiting work (using horrible methods having side-effects, but that's not the point).
Imagine you have this:
private int cnt;
private boolean a() {
cnt++;
return false;
}
private boolean b() {
cnt++;
return false;
}
If you execute the following:
cnt = 0;
if ( a() && b() ) {}
System.out.println( cnt );
It shall print 1.
While if you execute the following:
cnt = 0;
if ( a() & b() ) {}
System.out.println( cnt );
It shall print 2. Because in the latter case b() must be evaluated as per the language specs while in the first case b() must not be evaluated, as per the language specs.
You can use & in situations where you have to evaluate both subexpressions. For example, if they both have side effects that are observable by the rest of your application.
Perhaps the 2nd evaluation is in the form of an assignment statement or method call, in which case you might want it to execute. I wouldn't use bitwise operators in place of logical operators like this tho. If you need something to execute passed &&, then do it prior to your logical statement and store the result in a variable.
if(0 != ((a > b) ? 1 : 0) & ((c < d) ? 1 : 0)) {
// but really... (a > b) && (c < d), assuming no side-effects
}
...just use the logical operators (&& and ||) for conditions ;-) That is what they were designed for. If non-shortcircuit behavior is required, then restructure the code accordingly.
I think I have seen one case that had a somewhat valid use of & in this context, but I do not recall what it was so I mustn't have found it that valid ;-) In languages like C/C++ where there is no discreet "boolean" type, the (input) and result of & can be treated such that 0 -> false and non-0 -> true. As can be seen, however, Java has to jump through some fun to get bool -> int -> bool.
The only justification for a bit-wise operator is, well, bit-wise operations, IMOHO. Bit-wise operators are most useful when performing some sort of encoding including "bit fields" and "bit masks". They are also useful when dealing with fun arising from Java's signed-only bytes, etc.
I think the bigger (only?) point to take away is that && and || are short-circuiting -- they are actually the only operators with this behavior (arguments over ?: excluded); the rest is just to explain the eager-behavior of bit-wise operators. This just goes to re-enforce the rule: do not cause side-effects in conditionals (outside of a few well-accepted idioms, but even then, keep it simple).
Happy coding.
Examples of bit-wise usage:
Imagine the use of flags which are stored into a single "integer" slot in a serialized format:
int flags = 0;
if (this.encypted) {
flags |= EncryptedMode;
}
out.write(flags);
// later on
int flags = in.readInt();
this.encrypted = (flags & EncryptedMode) != 0;
Reading the "unsigned value" of a byte:
byte[] data = {-42, ...}; // read in from file or something
int unsignedByte = data[0] & 0xFF;
Your book is confusing things. For the most part, you will only use '&&' and '||'. The single ones, '&' and '|', are bitwise operators - you can read more about them here: http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
The use of a non-short-circuit operator may speed up performance-critical code by avoiding branch mis-prediction stalls, which could easily amount to a dozen or more clock cycles.
I'm trying to build an array of prime numbers in Java.
if(c % 2 != 0 || c % 3 != 0 || c % 5 != 0) {
n.add(c);
}
But my program seems to ignore the condition and just adds every number to my list.
But if I just use one condition for example,
if(c % 2 != 0)
The code works perfectly in ignoring any number which is a multiple of 2. What am I missing here?
You need to use logical and (&&) instead of or(||), as you want all conditions to be true before adding.
With logical or, each condition is evaluated from left to right, until finding one that matches.
Your condition right now evaluates to true if the number is not divisible by any of (2,3,5). This holds for all numbers except multiples of (all of) 2, 3, and 5. Try logical and (&&) instead of logical or (||).