Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to PROVE the precedence of '&&' and '||' by coding in Java?

I know from somewhere that logical AND: && has a higher precedence than logical OR: || in Java, but until now I haven't found any clue about how this precedence really acts. What would happen if I didn't know about the precedence of the two and what mistake would I make? I tried to write some code to PROVE the precedence of && and || but failed, for example:

boolExp1 || boolExp2 && boolExp3 || boolExp4

The code above produces the same results no matter the precedence of && and ||, that is,

false || false && true || false

results in false no matter what the precedence is.

I want a method or function that can PROVE the precedence of && and ||. It should produce different results depending on the precedence of && and ||. Is it possible?

like image 219
pf_miles Avatar asked Dec 14 '10 06:12

pf_miles


4 Answers

If && didn't have higher precedence than ||, then this expression:

a || b && c

would be evaluated like this:

(a || b) && c

To verify if this is the case or not, you can generate all combinations of a, b, and c, and compare the result of these two expressions, to see if they are always equal or not, that is:

  1. For all combinations of a, b, and c
  2. Verify that: (a || b && c) == ((a || b) && c)

Sample code:

for (int i = 0; i < 8; ++i) {
    boolean a = ((i >> 2) & 1) == 1;
    boolean b = ((i >> 1) & 1) == 1;
    boolean c = (i & 1) == 1;
    boolean x1 = (a || b && c);
    boolean x2 = ((a || b) && c);

    if (x1 != x2) {
        System.out.println(String.format("%s %s %s", a, b, c));
        System.out.println(String.format("   %s || %s  && %s => %s", a, b, c, x1));
        System.out.println(String.format("  (%s || %s) && %s => %s", a, b, c, x2));
    }
}

The output:

true false false
   true || false  && false => true
  (true || false) && false => false
true true false
   true || true  && false => true
  (true || true) && false => false

As such, && has higher precedence than ||.

like image 57
janos Avatar answered Nov 17 '22 18:11

janos


You cannot prove anything useful about a programming language by just writing / running examples. For all you know, the compiler might be implemented so as to compile code in an illogical, inconsistent or non-deterministic fashion.

Even if you assume deterministic compilation and deterministic execution, the only thing that compiling / running an example proves is that that particular example exhibits a particular behavior. You cannot logically generalize from one example to another one, because without reference to a specification the compiler is just a black box. (Your very next example could be the one that is handled in a totally counter-intuitive fashion.)

The correct way to develop an understanding of a programming language is to read the language specification, a good textbook or a good tutorial. Combine this with writing code to confirm your understanding.

If you rely solely on reading example code and writing test programs, you are liable to pick up misconceptions, and bad habits that can be painful to unlearn.

like image 30
Stephen C Avatar answered Nov 17 '22 19:11

Stephen C


Let's take your example expression:

boolExp1 || boolExp2 && boolExp3 || boolExp4

Now we believe that acts as:

boolExp1 || (boolExp2 && boolExp3) || boolExp4

right?

So let's suppose the opposite is true, and it's actually

(boolExp1 || boolExp2) && (boolExp3 || boolExp4)

What values of boolExp1 etc would give us different results?

Well, let's take:

boolExp1 = true
boolExp2 = false
boolExp3 = false
boolExp4 = false

Under the "&& has higher precedence" rules, the result would be true. Under the "|| has higher precedence rules", the result would be false. A quick test shows that the expression evaluates to true, however.

Of course, this doesn't actually prove that && has higher precedence than || - merely that || doesn't have higher precedence than &&. We could consider whether they have equal precedence - and test that with other expressions in a similar way... find a sample expression and values which would give different results under different precedence rules, and test them.

Ultimately though, I prefer:

  • To trust the spec unless I have specific doubts
  • To use parentheses to make my intentions clear

I wouldn't use the first expression "as is" in the first place... because unless you actually know the precedence rules (and I suspect many Java devs don't - I couldn't swear that I'd have got && and || right) you're in the dark. Better to make it explicit and clear where there's any doubt.

like image 27
Jon Skeet Avatar answered Nov 17 '22 19:11

Jon Skeet


I too had this same question but the answer was practically giving to me. Here is my example:

true || true && false

is equivalent to

true || (true && false)

So with this example it is easy to see that under the hood in Java the logical && has a higher precedence than ||.

like image 6
WorkMindDesigns Avatar answered Nov 17 '22 19:11

WorkMindDesigns