89

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?

Josiah Ruddell
  • 29,697
  • 8
  • 65
  • 67
  • 25
    It's that way in the language because they have to make a decision. Personally, I don't care which has precedence; I'd use parenthesis to make sure I'm getting the result I expect. It's not about why it does what it does; it's about being able to figure out what the code is doing when you back to it weeks, months or years later. – Jeff Siver Jul 28 '09 at 21:04
  • 28
    @Jeff: That's not correct. There is a mathematical basis for this decision - it's called **boolean algebra**. – EFraim Jul 28 '09 at 21:09
  • I also wonder how often short circuiting is affecting these results vs how often its due to some sort of precedence. And how would you know? Hmm... – Steve Wortham Jul 28 '09 at 21:09
  • 4
    @TheSteve: short-circuiting is not affecting expression result. It only affects side effects. – EFraim Jul 28 '09 at 21:11
  • I think I know what you mean. I guess short circuiting is just something that requires you to write your test case carefully. – Steve Wortham Jul 28 '09 at 21:13
  • 11
    The fact that you even have to consider it means you shouldn't rely on the next guy knowing, if there is a question that anyone in the office might possibly have to spend 3 seconds thinking about it, then invest the .5 seconds to add a ( and a ) – Bill K Jul 28 '09 at 21:59
  • 39
    Let me see if I've got this straight. Your coworker has a belief about the language. That belief is contradicted by both the specification and the implementation. Your claim is consistent with the specification and the implementation. So why are YOU the one trying to construct a proof? The burden of proof is upon the person who has the crazy belief, not the person who has the sensible belief. I wouldn't waste any more time on this; if they want to spend their time trying to prove something false, let 'em. – Eric Lippert Jul 28 '09 at 22:00
  • 1
    I appreciated the eloquent expression of frustration with a couple of hypens "all-the-time" – Andy Dent Aug 17 '15 at 07:58
  • 2
    *"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 Jul 28 '09 at 23:44

6 Answers6

136

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
Noctis
  • 11,507
  • 3
  • 43
  • 82
Francis B.
  • 7,018
  • 2
  • 32
  • 54
  • Nice example of why it is important. – RichardOD Jul 28 '09 at 21:11
  • 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 Jul 28 '09 at 21:40
  • 13
    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 Jul 28 '09 at 22:01
  • The above example doesn't prove the point because it ignores short-circuiting! Let's say we changed C# so that || had higher precedence than &&. Then true || true && false would STILL return true. Why? Because || will not evaluate the rest of the statement due to short-circuiting as stated in http://msdn.microsoft.com/en-us/library/aa691310(VS.71).aspx – James Jul 28 '09 at 23:07
  • 7
    @James, no it would not.. If || had higher precedence, then the expression would be equivilent to (true || true) && false => False, not true, because thafter evaluating {true || true) as true, what would be left is true && false, which would NOT create a short circuit – Charles Bretana Jul 28 '09 at 23:15
  • @Charles Bretana, in my understanding, true || true && false performs no operations. It simply returns true due to short-circuiting. The || and && operators are not evaluated. – James Jul 28 '09 at 23:35
  • 7
    @James, No, if || had higher precedence the clr would evaluate this as (true or true) && false. so first it would evaluate (true || true). Within this expression, yes, short-circuiting occurs because for an OR expresion, if the first part is true, there is no need to evaluate the second part. So this evaluates to true. Now we have true && false. For && operations, short circuiting only occurs if the first part is FALSE, which in this case it is not, so both parts have to be true for A && B to evaulate as true. So it evaluates both parts and comes up with false – Charles Bretana Jul 29 '09 at 04:58
  • 16
    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 Jul 29 '09 at 05:42
  • @Charles Bretana, my conjecture may have been made in haste, but I still stand by the fact that || and && are not evaluated in true || true && false. Run the code I posted as an answer and see the result. Try to come up with actual code to prove me otherwise. – James Jul 29 '09 at 15:41
  • @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 && are not evaluated at all; and if the OP's coworker knew that fact, then the coworker could simply say that the proof is illogical since it hinges upon all three statements evaluating all six operations. If you didn't know the only && operation that is actually evaluated is (true || true) && false. – James Jul 29 '09 at 15:54
  • Short circuiting DOES change the result! Compare `true | false & false` with `true | false && false`. The first expression is `true`, but the second expression is `false`. Short circuiting will only keep the result the same if you use only short circuited operators in your expression. – comecme Feb 03 '13 at 18:18
  • 11
    @comecme That isn't a result of short circuiting, but of changing the order of operation. The & operator has higher precedence than the | operator, so the first expression would behave like `true | (false & false)`. This would evaluate to true because `false & false = false`, then `false | true = true`. However, the | operator has a higher precedence than the && operator, so the second expression would behave like `(true | false) && false`. This would evaluate to false because `true | false = true`, then `true && false = false`. – Abion47 Mar 05 '13 at 00:04
14

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
  • 62,489
  • 19
  • 106
  • 139
  • 1
    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 Jul 28 '09 at 21:46
  • 2
    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 Jul 28 '09 at 22:03
  • 2
    This would be an amusing prank. :) – James Jul 28 '09 at 23:12
  • 1
    So, if you change `||` to `|` and leave the `&&`, the result of the expression changes from true to false? So you'd normally either use `|` together with `&`, or use `||` together with `&&`. – comecme Jan 30 '13 at 21:44
6

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

bool result = true || false && false;
Max Schmeling
  • 12,363
  • 14
  • 66
  • 109
  • This distinguishes between && having higher precedence and || having higher precedence, but does not distinguish between || having higher precedence and && and || having equal precedence. Remember that if operators are equal in precedence they are simply evaluated left-to-right. – Tyler McHenry Jul 28 '09 at 21:12
  • 1
    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 Jul 28 '09 at 21:19
5

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
  • 12,811
  • 4
  • 46
  • 62
  • 10
    In some languages, neither one does (e.g. Smalltalk). Analogies can be deceiving. – Pavel Minaev Jul 28 '09 at 21:28
  • 1
    That's not analogy. That's reasoning behind this particular feature of C-family languages. – EFraim Jul 28 '09 at 21:42
  • 1
    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 Jul 28 '09 at 21:49
  • 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 Jul 29 '09 at 05:43
  • 11
    I don't know about the other downvoter, but *I* downvoted because this has nothing to do with the question. It happens to match... but anyone can design a language Foo# where this isn't true; how would your "**proof** with logic" work then? It might explain why this precedence was chosen, but it doesn't help establish that the compiler I have installed actually behaves that way. – Roman Starkov Dec 30 '11 at 02:00
  • 2
    @romkyns: It has everything to do with the language. C and C++'s rules derive from the laws of algebra. That's why + has smaller precedence than *. You can argue all you want but you are both wrong and obnoxious. Your compiler behaves according to the language specification and the language specification has it basis in algebra, Q.E.D. – EFraim Jan 02 '12 at 18:02
  • 3
    QED? Do you know what it means to _prove_ something? The language might be _intended_ to follow the laws of algebra, but how do you _prove_ that between that intention and the huge amount of engineering effort, nobody messed up and accidentally violated it or misread the spec when implementing the precedence rules? (unlikely, but not impossible) – Roman Starkov Jan 02 '12 at 18:27
  • 2
    @EFraim: Which algebra? You are assuming a specific algebra. The commonly-accepted algebra for regular expressions in theoretical computer science is equivalent to finite-state automata; according to your logic, therefore, .NET regular expressions should also be. But they are not! Q.E.D.!!! ;-) – Timwi Jan 02 '12 at 18:39
  • @Timwi: No, I am assuming what you have learned in either first or second grade. Principle of least surprise applies to programming language design too ;) – EFraim Jan 02 '12 at 18:56
  • 2
    @EFraim: Exactly, it’s a principle. Not a law. Hence, your reasoning is a good guess, but not a proof. – Timwi Jan 02 '12 at 21:22
  • 1
    Also, I don’t believe you that you learnt Boolean algebra in first or second grade. – Timwi Jan 02 '12 at 21:53
  • @Timwi: My example related to addition/multiplication, in case I was not clear. To clarify - *of course* it's not a law, but neither it's an arbitrary decision of C's designers. – EFraim Jan 03 '12 at 18:12
  • 3
    I think the point you are making is valid, it's just that it doesn't qualify as a "proof", where a proof is something much more rigorous than just explaining how and why the language designers decided to do things. "They based it on algebra, therefore it does necessarily work like algebra" is not a rigorous proof (and actually saying it that way is logically invalid). – Dave Cousineau Feb 03 '13 at 02:34
  • 1
    Also, how would you prove to the layman that AND is equivalent to multiplication and OR is equivalent to addition? Now you have two problems. – tripleee Oct 06 '16 at 05:51
  • @tripleee: No need to prove anything, they are defined that way in Boolean algebra. I am talking C# layman here, not math layman. – EFraim Oct 06 '16 at 10:40
2

false || true && true

Yields: true

false && true || true

Yields: true

veggerby
  • 8,940
  • 2
  • 34
  • 43
  • 1
    The first statement is going to return true no matter what order you do the operations in. The second will only return false if || is evaluated first. Since it does return true, either && is evaluated first, or they have the same precedence and are evaluated left-to-right. A third statement `true || true && false` (which also returns true) can only be true if && is evaluated first. – CodeHxr Sep 20 '18 at 14:26
-5

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
  • 659
  • 1
  • 5
  • 15