views:

905

answers:

9

We get into unnecessary coding arguments at my work all-the-time. Today I asked if conditional AND (&&) or OR (||) had higher precedence. One of my coworkers insisted that they had the same precedence, I had doubts, so I looked it up.

According to MSDN AND (&&) has higher precedence than OR (||). But, can you prove it to a skeptical coworker?

http://msdn.microsoft.com/en-us/library/aa691323(VS.71).aspx

bool result = false || true && false; // --> false
// is the same result as
bool result = (false || true) && false; // --> false
// even though I know that the first statement is evaluated as 
bool result = false || (true && false); // --> false

So my question is how do you prove with code that AND (&&) has a higher precedence that OR (||)? If your answer is it doesn't matter, then why is it built that way in the language?

+3  A: 

Wouldn't this get you what you're after? Or maybe I'm missing something...

bool result = true || false && false;
Max Schmeling
Tyler McHenry
I should say though that this does work as a proof for C# in particular (or really any normal language), since the actual result you do get is unambiguous. It's just not a *general* method for working out the relative precedence in case you're up against an esoteric language that contradicts boolean algebra on purpose.
Tyler McHenry
+17  A: 

Change the first false by true. I know it seems stupid to have (true || true) but it proves your point.

bool result = true || true && false; // --> true 
result = (true || true) && false; // --> false
result = true || (true && false); // --> true
Francis B.
Nice example of why it is important.
RichardOD
What if you reverse the order of the operators? Just to ensure that it isn't the result of some short-circuiting element.
JB King
Short circuiting only ever occurs when the result of the boolean expression is known; short circuiting can not change the result of a boolean expression.
Captain Segfault
James
Charles Bretana
James
Charles Bretana
Could we just stop all this non-sense, which seems to repeat itself ad-nauseum?! Repeat with me : SHORT-CIRCUITING DOES NOT CHANGE RESULT. Short-circuiting only applies when the result is already known. SHORT-CIRCUITING ONLY AFFECTS SIDE-EFFECTS
EFraim
@EFraim, well, ok, we'll stop if it really bothers you that mch... we're truly sorry you couldn't ignore this terrible irritant and proceed with the rest of your life undisturbed by our discussion... if we could humbly ask, could you post a list of the other topics that might bother you to this extent so we can also avoid them in all our activities in the future?
Charles Bretana
James
@EFraim. "Short-circuiting does not change result." I have never mentioned otherwise. I'm simply talking about the proof to the OP's coworker; the fact that JB King and myself are skeptical of this proof goes to show it is missing something. I know that the || and
James
+1  A: 

false || true && true

Yields: true

false && true || true

Yields: true

veggerby
+6  A: 

You don't prove it with code but with logic. AND is boolean multiplication whereas OR is boolean addition. Now which one has higher precedence?

EFraim
In some languages, neither one does (e.g. Smalltalk). Analogies can be deceiving.
Pavel Minaev
That's not analogy. That's reasoning behind this particular feature of C-family languages.
EFraim
By the way the Smalltalk sample is not really representative: it has no operator precedence for math operators at all. In the same way you could argue they have the same precedence in Scheme.
EFraim
Just let me undestand the reason for the downvote: a). You don't agree with principles of boolean algebra. b). You don't know what it is.
EFraim
A: 

There are two entities -- one tells the truth and the other always lies...

Hardryv
That's supposed to be a comment I guess
EFraim
Actually it's from a old riddle referenced by a scene in the movie 'Labyrith' this thread reminded me of when I read it... not truly relevant to the 'overflowing of stacks', but I was moved to giv e it a mention anyhow.
Hardryv
+2  A: 

If you really want to freak him out try:

bool result = True() | False() && False();

Console.WriteLine("-----");
Console.WriteLine(result);

static bool True()
{
    Console.WriteLine(true);
    return true;
}

static bool False()
{
    Console.WriteLine(false);
    return false;
}

This will print:

True
False
False
-----
False

Edit:

In response to the comment:

In C#, | is a logical operator that performs the same boolean logic as ||, but does not short-circuit. Also in C#, the | operator has a higher precedence than both || and &&.

By printing out the values, you can see that if I used the typical || operator, only the first True would be printed - followed by the result of the expression which would have been True also.

But because of the higher precedence of |, the true | false is evaluated first (resulting in true) and then that result is &&ed with false to yield false.

I wasn't trying to show the order of evaluation, just the fact that the right half of the | was evaluated period when it normally wouldn't be :)

John Rasch
a. Why mixing boolean and bitwise operator?b. Why do you insist on printing it? What the order of evaluation has to do with it?
EFraim
Response to response: | is still binary. It is just that for bool it performs the desired operation - as it does in C++. To clarify it MS documents it as logical for bool's. But IMHO it just muddies water.
EFraim
This would be an amusing prank. :)
James
A: 

You cannot just show the end result when your boolean expressions are being short-circuited. Here's a snippet that settles your case.

It relies on implementing & and | operators used by && and ||, as stated in MSDN 7.11 Conditional logical operators

public static void Test()
{
    B t = new B(true);
    B f = new B(false);

    B result = f || t && f;

    Console.WriteLine("-----");
    Console.WriteLine(result);
}

public class B {
    bool val;
    public B(bool val) { this.val = val; }
    public static bool operator true(B b) { return b.val; }
    public static bool operator false(B b) { return !b.val; }
    public static B operator &(B lhs, B rhs) { 
        Console.WriteLine(lhs.ToString() + " & " + rhs.ToString());
        return new B(lhs.val & rhs.val); 
    }
    public static B operator |(B lhs, B rhs) { 
        Console.WriteLine(lhs.ToString() + " | " + rhs.ToString());
        return new B(lhs.val | rhs.val); 
    }
    public override string ToString() { 
        return val.ToString(); 
    }
}

The output should show that && is evaluated first before ||.

True & False
False | False
-----
False

For extra fun, try it with result = t || t && f and see what happens with short-circuiting.

James
Short-circuiting has nothing to do with expression result. Can we just get over it?
EFraim
+2  A: 

We get into unnecessary coding arguments at my work all-the-time.

Well thats your problem. Being the right one is not as important as working together. The pragmatic solution is to use parenthesis to make it explicit.

Frank Schwieterman
A: 

We get into unnecessary coding arguments at my work all-the-time... If your answer is it doesn't matter, then why is it built that way in the language?

I always use parentheses to enforce precedence. But then that comes from my electrical engineering background. These 2 are different circuits:

result = (A || B) && C; 
result = A || (B && C);

And another reason that I put the parens in myself is that some of the code our company uses approaches 15 years old (we've got some shipping products that started life back then). You'll never know ahead of time if C# version 21.0 will have the same precedence that the current C# has. I'm old enough to remember when a "new" version of Forth came out that swapped the values of true and false: a heck of a lot of code quit working, and a heck of a lot of programmers changed languages. And a previous employer had several apps behave strangely when switching from one allegedly-standards-compliant C++ compiler to a different allegedly-standards-compliant C++ compiler only to find out that they actually didn't have the same rules of precedence.

Tangurena
C# 21 will have the same operator precedence as C, certainly
EFraim
C# carefully specifies the exact rules for precedence, associativity and order of evaluation. (Remember, those are three different things; don't get them mixed up.) However, C/C++ only specifies the first two -- in C/C++, sequence point order is defined, but subexpression evaluation order is NOT. C# will always have the same rules for all three, but any two C/C++ implementations are permitted to use any evaluation ordering they choose. The problem you ran into when switching C++ compilers was almost certainly NOT a precedence problem; it was an order of evaluation problem.
Eric Lippert