Conditional XOR?
Asked Answered
B

12

110

How come C# doesn't have a conditional XOR operator?

Example:

true  xor false = true
true  xor true  = false
false xor false = false
Budbudapest answered 28/6, 2011 at 14:12 Comment(15)
How does != work as a substitute?Paracasein
C# does have an xor operator ( x ^ y ). I therefore deny the premise of the question. Can you explain why you believed that C# does not have an xor operator? I am interested to learn why people believe false things about C#.Isothermal
@Eric Lippert: I think he's referring to logical operators (& | ^) vs conditional operators (&& ||). But you're right (of course), there is a logical XOR...Scabies
@BoltClock: Oh, if the question is "why is there no short-circuiting xor operator?" -- how could there be? With "and" if the first argument is false you don't need to evaluate the second. With "or", if the first argument is true then you don't need to evaluate the second. You always need to evaluate both arguments for xor, so there is no short circuiting possible.Isothermal
@Eric: Looks like that'd be the (The Evil Greebo's) answer.Scabies
The question itself is one better suited to Microsoft - and so that's a decent reason to downvote - but if whoever downvoted it did so because of the ^ operator, then you need to read with more attention to detail, because the question was conditional vs. logical, not simply "why isn't there an XOR".Spitfire
All the answers even the accepted one are thoroughly incorrect. If I answer the question correctly, can my answer be selected as the best answer?Rivy
@SimpleFellow, I'm intrigued. Why not post an answer, and find out?Soane
@ Marc L. Ok as you asked.Rivy
Seems like there's a lot of confusion and debate about the logical ^ operator in the answers, which is odd since MS has kept this consistently well documented for every VS version since 2003, complete with code examples: msdn.microsoft.com/en-us/library/zkacc7k1(v=vs.71).aspxMartell
Note that the question asked is WHY - not how do I make one.Spitfire
@EricLippert: It's been a few years, and maybe you know by now, but as it hasn't been posted here explicitly I'd like to respond to your comments about people believing false things about C# and about the question being about a short-circuiting xor operator. As you well know, the difference between |/& and ||/&& in C# is that the latter are short-circuiting while the former are not. As you also well know, this also means the latter are not usable for operand types which do not define a short-circuiting logic (operators false and true). <to be continued>Dona
@EricLippert <continuation>: Because when dealing with boolean conditions the short-circuiting version is most often desired (and is the de facto standard, taught ubiquitously, with many textbook examples not mentioning the other version at all), and because for bit-wise operations on the common numeric types only the non-short-circuiting version of the operators is available, in practice what happens is that users of the language naturally develop the misconception that | and & are for bit-wise operations whereas || and && are for boolean operations. <to be continued>Dona
@EricLippert <continuation>: Under this misconception, people are not even aware of the distinction between short-circuiting and non-short-circuiting (albeit they might be aware that the boolean versions of the operators do short-circuit while the bit-wise versions do not). And under this misconception, people expect ^ to mean bit-wise xor and ^^ to mean boolean xor. And when noticing the existence of the ^ operator and the lack of a corresponding ^^ operator, their question is why there is no boolean version of xor, not why there is no short-circuiting version. <to be continued>Dona
@EricLippert <continuation>: So to summarise, the reason is that the short-circuiting distinction is quite implicit, that is it's not obvious or evident from typical usage examples alone. Clarification: I'm not saying it's not a good distinction, not a good choice of operators, or that the design of the language around this feature is flawed in any way. Just that it's a bit unreasonable to expect average users of the language to be aware of such subtleties.Dona
S
135

In C#, conditional operators only execute their secondary operand if necessary.

Since an XOR must by definition test both values, a conditional version would be silly.

Examples:

  • Logical AND: & - tests both sides every time.

  • Logical OR: | - test both sides every time.

  • Conditional AND: && - only tests the 2nd side if the 1st side is true.

  • Conditional OR: || - only test the 2nd side if the 1st side is false.

Spitfire answered 28/6, 2011 at 14:17 Comment(9)
An XOR operator would not violate the convention "conditional operators only execute their secondary operand if necessary". It would just always be necessary.Garganey
Conditional XOR could be a nice and elegant shortcut for some particular patterns, although not sure if justified enough to include it in the language. An example of such patterns where XOR might prove useful, is Conditional Negation: When a Boolean expression should be negated or not, given a second boolean expression.Stonebroke
Haven't responded to this in some time but to respond to popular comment by @KhyadHalda : Why would you ever build something you know would never be used? You'd be deliberately writing dead code.Spitfire
Given that a conditional XOR operator wouldn't violate the convention you define (Khyad's comment), coupled with the fact that it would actually be useful in some cases, it pretty much negates any "silliness" you ascribe to such an operator existing.Industrialist
How, ever, would a conditional XOR ever be useful? A conditional XOR cannot ever evaluate without comparing both sides to determine that they are or are not equal. Even the notion of a conditional XOR comparing two bools must still check the value of each bool and test the equality.Spitfire
Addendum - in the suggested case where you must negate a boolean, in c#, with a conditional XOR, how would you write that? given bool b1 and bool b2 if b1 must equal !b2 then b1 = !b2 is an assignment of an inversion. The "conditional xor" version would do what? b1 = (true ^ b2) ? If so that would be assignment of the result of a comparison of both sides, which doesn't seem like any kind of shortcut to the simpler assign the inversion.Spitfire
It's as silly as a conditional addition operator. Why not make another operator for conditional addition, where (a+b) only evaluates b when b is necessary? Just like with conditional XOR, this wouldn't violate the convention of conditional operators, it's just that the second argument would always be necessary. There's no use case for this ever. And I'm not just being pedantic with this example -- the XOR operation is essentially a 1-bit addition.Virgy
@TheEvilGreebo The boolean negation pattern described is not "b1 = !b2", but rather "if(b2) b1 = !b1; if(b1) { code }". I came here seeing if there was a clean way to do this without reassigning to b1, since it slightly offends my immutability aesthetic. Conditional xor would be one way of achieving that: "if(b1 ^^ b2) { code }".Harmonist
No that would not enforce a conditional or (xor) state. If (b2) {b1 = !b1} would simply cause b1 to change its state if b2 were true. If b1 were already 0 then you'd end up with b2 and b1 both being 1 which would not meet the conditional xor enforcement being discussed.Spitfire
B
345

Conditional xor should work like this:

true xor false = true
true xor true = false
false xor true = true
false xor false = false

But this is how the != operator actually works with bool types:

(true != false) // true
(true != true) // false
(false != true) // true
(false != false) // false

So as you see, the nonexistent ^^ can be replaced with existing !=.

Booklet answered 2/2, 2013 at 18:2 Comment(7)
This is actually the only answer that addresses the question directly and correctly.Curator
I am sitting here facepalming myself that I didn't realize != would work for this.Mcgarry
The answer is correct but the comments aren't. It does not address the question, which is "why doesn't C# have a conditional XOR?". Strictly speaking this isn't a logical operator, it's a relational equality operator. While the result is the same as XOR, it is in a different class. It only compares to XOR when testing two boolean values, and both sides of the operator still must be evaluated.Spitfire
@TheEvilGreebo - What you say is true; the != operator is not technically a conditional XOR operator. However, this answer effectively says, "A conditional XOR operator doesn't exist because the != operator does." That's how I read it, anyway.Industrialist
I think pretty much every one ended up to this post actually wanted to write XOR on Booleans. like there is logical AND and OR but nothing as XOR. or at least we didn't realize != :) @TheEvilGreeboCorpuz
I just realized ^ also works for Booleans :| @Mcgarry https://mcmap.net/q/194706/-conditional-xorCorpuz
It still bums me out that there's no ^^ operator, because I could have said a == b ^^ c == d, but I can't get away with a == b != c == d. I have to add parentheses.Brigidabrigit
S
135

In C#, conditional operators only execute their secondary operand if necessary.

Since an XOR must by definition test both values, a conditional version would be silly.

Examples:

  • Logical AND: & - tests both sides every time.

  • Logical OR: | - test both sides every time.

  • Conditional AND: && - only tests the 2nd side if the 1st side is true.

  • Conditional OR: || - only test the 2nd side if the 1st side is false.

Spitfire answered 28/6, 2011 at 14:17 Comment(9)
An XOR operator would not violate the convention "conditional operators only execute their secondary operand if necessary". It would just always be necessary.Garganey
Conditional XOR could be a nice and elegant shortcut for some particular patterns, although not sure if justified enough to include it in the language. An example of such patterns where XOR might prove useful, is Conditional Negation: When a Boolean expression should be negated or not, given a second boolean expression.Stonebroke
Haven't responded to this in some time but to respond to popular comment by @KhyadHalda : Why would you ever build something you know would never be used? You'd be deliberately writing dead code.Spitfire
Given that a conditional XOR operator wouldn't violate the convention you define (Khyad's comment), coupled with the fact that it would actually be useful in some cases, it pretty much negates any "silliness" you ascribe to such an operator existing.Industrialist
How, ever, would a conditional XOR ever be useful? A conditional XOR cannot ever evaluate without comparing both sides to determine that they are or are not equal. Even the notion of a conditional XOR comparing two bools must still check the value of each bool and test the equality.Spitfire
Addendum - in the suggested case where you must negate a boolean, in c#, with a conditional XOR, how would you write that? given bool b1 and bool b2 if b1 must equal !b2 then b1 = !b2 is an assignment of an inversion. The "conditional xor" version would do what? b1 = (true ^ b2) ? If so that would be assignment of the result of a comparison of both sides, which doesn't seem like any kind of shortcut to the simpler assign the inversion.Spitfire
It's as silly as a conditional addition operator. Why not make another operator for conditional addition, where (a+b) only evaluates b when b is necessary? Just like with conditional XOR, this wouldn't violate the convention of conditional operators, it's just that the second argument would always be necessary. There's no use case for this ever. And I'm not just being pedantic with this example -- the XOR operation is essentially a 1-bit addition.Virgy
@TheEvilGreebo The boolean negation pattern described is not "b1 = !b2", but rather "if(b2) b1 = !b1; if(b1) { code }". I came here seeing if there was a clean way to do this without reassigning to b1, since it slightly offends my immutability aesthetic. Conditional xor would be one way of achieving that: "if(b1 ^^ b2) { code }".Harmonist
No that would not enforce a conditional or (xor) state. If (b2) {b1 = !b1} would simply cause b1 to change its state if b2 were true. If b1 were already 0 then you'd end up with b2 and b1 both being 1 which would not meet the conditional xor enforcement being discussed.Spitfire
B
42

There is the logical XOR operator: ^

Documentation: C# Operators and ^ Operator

The documentation explicitly states that ^, when used with boolean operands, is a boolean operator.

"for the bool operands, the ^ operator computes the same result as the inequality operator !=".

(And as noted in another answer, that's exactly what you want).

You can also bitwise-xor integer operands with ^.

Bumgarner answered 28/6, 2011 at 14:15 Comment(4)
Logical, not conditional. Logical and = &, conditional and = &&. He's asking about Conditional.Spitfire
It is binary, not logical. It assumes that bools are either 0 or 1 which is not true on the CLR.Curator
sorry, this answer does not actually answer the question about CONDITIONAL operators. this is a bit opperatorRipsaw
For the record, the documentation linked in this answer explicitly states that ^, when used with boolean operands, is a boolean operator. "for the bool operands, the ^ operator computes the same result as the inequality operator !=". You can also bitwise-xor integer operands with ^. C# is not C.Unroot
Y
27

Just as a clarification, the ^ operator works with both integral types and bool.

See MSDN's ^ Operator (C# Reference):

Binary ^ operators are predefined for the integral types and bool. For integral types, ^ computes the bitwise exclusive-OR of its operands. For bool operands, ^ computes the logical exclusive-or of its operands; that is, the result is true if and only if exactly one of its operands is true.

Maybe the documentation has changed since 2011 when this question was asked.

Yee answered 13/6, 2016 at 11:50 Comment(2)
been programming in c# a long time, never knew this! thanks @Yee !Ripsaw
This is good information but seems more appropriate as a comment or edit to the other answer that mentions ^ and predates this one by five years. I doubt anything has changed.Succor
R
13

As asked by Mark L, Here is the correct version:

 Func<bool, bool, bool> XOR = (X,Y) => ((!X) && Y) || (X && (!Y));

Here is the truth table:

 X | Y | Result
 ==============
 0 | 0 | 0
 1 | 0 | 1
 0 | 1 | 1
 1 | 1 | 0

Reference: Exclusive OR

Rivy answered 29/12, 2015 at 11:4 Comment(1)
The question asked was WHY doesn't C# have a conditional XOR operator. This does not answer the question. As to the function itself: this function does operate as conditional XOR - however the question is, is it more efficient than the non-conditional XOR? In order to test for exclusive truth, XOR must confirm that one and exactly one result is true. This means both sides must be evaluated and compared. The function above tests both sides of an and condition while inverting one value, at a minimum. Do we know internally if this is any different than XOR?Spitfire
I
5

Oh yes, it does.

bool b1 = true;
bool b2 = false;
bool XOR = b1 ^ b2;
Ingeborgingelbert answered 28/6, 2011 at 14:15 Comment(7)
It is a binary operator, not a logical one. It assumes that bools are either 0 or 1 which is not true on the CLR. So this code can actually fail to work.Curator
@usr, In C#, the ^ operator is logical when applied to two Boolean operands. You commented an awful lot through these answers, did you ever run any code to test your hypothesis?Soane
@MarcL. I did: pastebin.com/U7vqpn6G Prints true, although true ^ true is supposed to be false. bool is not always equal to 0 or 1. It is not a logical type on the CLR. It is an 8 bit quantity with arbitrary contents. I could have generated verifiable IL to demonstrate the issue as well.Curator
@usr, okay, so you've managed to show the logical operators appear to act on Booleans by applying bitwise to the underlying 8-bit value--for the record, CreateBool(1) & CreateBool(2) will also yield False. And that this is not sufficient if the CLR is roughed up a bit. But, as fun as this has been, in what scenario (where one hasn't plainly abused the CLR) does this distinction make any difference whatsoever?Soane
When using other CLR languages than C# for example. I repeat: I could have used ILASM to create a fully verifiable, safe assembly that does this (at the IL level a boolean value is just an i1, just like a byte is). This is 100% defined and safe managed behavior. The CLR is not roughed-up.; The first time I saw this behavior was when using Microsoft Pex.Curator
@EdPlunkett , I don't think your truck is with me. usr showed that internally it is in fact a binary operator. The "abuse" of which I complained was the means by which he proved it, which I still maintain is too edgy. It may happen, but puts the use of Boolean so thoroughly into no-man's land that to deploy it as CLR-safe would be dangerous at best, abusive (if not malicious) at worst, and should be treated as a bug. What usr proves is that internally C# is more like C than either of us thought. Whether code that does this should be considered valid is another question.Soane
@MarcL. Whoops, you're quite correct. I somehow failed to notice your comment that says "In C#, the ^ operator is logical when applied to two Boolean operands.", and I didn't read the comment I did reply to very closely. My apologies!Unroot
T
4

Conditional xor doesn't exist, but you can use logical one because xor is defined for booleans, and all conditional comparisons evaluate to booleans.

So you can say something like:

if ( (a == b) ^ (c == d))
{

}
Tardif answered 28/6, 2011 at 14:19 Comment(9)
It is a binary operator, not a logical one. It assumes that bools are either 0 or 1 which is not true on the CLR. So this code can actually fail to work.Curator
@Curator what do you mean CLR? This worked for me, not sure if I missed an edge case here...Seda
@Spencevail you probably were not thinking about the case that a non-false boolean might not have integer representation 1. This is a little known fact. You can end up in a situation where the xor of two non-false booleans is still non-false! That said in this particular code the xor operator is only ever applied to values in [0,1] so that my comment does not (fully) apply.Curator
@Curator when would a boolean expression evaluate to something other than 0 or 1? Again, not disagreeing, just looking for more info on the subject. Would something like: swift let firstBool: Bool = someExpression let secondBool: Bool = anotherExpression if (firstBool ^ secondBool) { println("Prints only if first or second, but not both") } Not work as expected?Seda
@Spencevail that is exactly the case that can fail. It is possible to create a safe managed code function CreateBool(byte) that converts a byte into a bool of the same bits. Then, CreateBool(1) ^ CreateBool(2) is true, but CreateBool(1) is true and CreateBool(2) is true as well! & is also vulnerable.Curator
Actually, I just reported a RyuJIT bug because they did not consider this possibility and compiled && as if it were & which is a miscompilation.Curator
@Curator Is there not a workaround for the issue you mention?Slattery
@Curator Also, can you post your on answer elaborating on the issue? I think it would be cleaner.Slattery
@Slattery Maybe I should but since the vote counts are so high, nobody would see it... The 2nd highest answer is correct. It's simply the != operator :)Curator
G
3

While there is a logical xor operator ^, there is no conditional xor operator. You can achieve a conditional xor of two values A and B using the following:

A ? (!B) : B

The parens are not necessary, but I added them for clarity.

As pointed out by The Evil Greebo, this evaluates both expressions, but xor cannot be short circuited like and and or.

Gstring answered 28/6, 2011 at 14:21 Comment(3)
What's the difference between a logican ^ and a conditional ^ ? oOIngeborgingelbert
@Armen Tsirunyan The logical operators perform bitwise operations in types where that makes sense while the conditional operators operate on boolean values and return a boolean result. Considering boolean values: 0101 ^ 0011 has the value 0110.Gstring
no, you are completely wrong. there are both types of XOR's (they're called bitwise and logical, respectively) in C#. Both use the ^ symbol.Ingeborgingelbert
D
1

you can use:

a = b ^ c;

just like in c/c++

Dinette answered 28/6, 2011 at 14:16 Comment(0)
V
0

There is no such thing as conditional (short-circuiting) XOR. Conditional operators are only meaningful when there's a way to definitively tell the final outcome from looking at only the first argument. XOR (and addition) always require two arguments, so there's no way to short-circuit after the first argument.

If you know A=true, then (A XOR B) = !B.

If you know A=false, then (A XOR B) = B.

In both cases, if you know A but not B, then you don't know enough to know (A XOR B). You must always learn the values of both A and B in order to calculate the answer. There is literally no use case where you can ever resolve the XOR without both values.

Keep in mind, XOR by definition has four cases:

false xor true  = true
true  xor false = true
true  xor true  = false
false xor false = false

Again, hopefully it's obvious from the above that knowing the first value is never enough to get the answer without also knowing the second value. However, in your question, you omitted the first case. If you instead wanted

false op true  = false (or DontCare)
true  op false = true
true  op true  = false
false op false = false

then you can indeed get that by a short-circuiting conditional operation:

A && !B

But that's not an XOR.

Virgy answered 15/5, 2019 at 21:29 Comment(7)
I’m not seeing anything in this answer that isn’t in at least one answer above. I don’t see any indication that your short-circuitable un-xor is what OP was looking for, since he accepted an answer which assumes he wanted proper xor.Unroot
Mine is literally the only answer suggested so far that can produce the OP's requested truth table without evaluating the second argument.Virgy
Also the OP asked why there is no conditional XOR, and while the answers above do say correctly that it's because XOR requires two arguments, IMO the answers above didn't seem to say sufficiently explain WHY does XOR actually need two arguments. Obviously you feel otherwise, but to me it was apparent from the various comments on this page that the basic two-argumentness of XOR hadn't been fully explained to a complete beginner yet.Virgy
You talked me into it.Unroot
@Kevin Holt - Logical XOR is meaningful if you need one of the conditions to be true but not both. That you have to evaluate both conditions doesn't matter. The short circuit thing is a low level detail that you only have to worry about when dealing with performance critical code (control flow is slow). I'd be more concerned with what 'exclusive or' is supposed to mean when making a logical operator out of it. Namely, have it operate like the bitwise version (like the other operators), or make it an or that's exclusive (as many conditions as you want, but only one can be true).Upstretched
First off, short-circuits are not just for performance critical code. For example, "wroteFile = (FileOutputIsEnabled && TryToWriteTheFile().WasSuccessful())" is completely legal code, with drastically different outcomes for short-circuiting AND vs non-short-circuiting AND. Sure, performance is another (more common) way to use it, but it's by no means the only use of it.Virgy
Second, there is no such thing as short-circuiting XOR. Let's clarify what you mean by "you need one of the conditions to be true but not both". Do you mean "you need at least one of the conditions to be tru?" Because that's an OR, not an XOR, and yes there is a short-circuiting version of that. Do you mean "you need exactly one of the conditions to be true, but not neither and not both?" Because that needs to know both input values, and there's no way to short-circuit it. The only way to get a short-circuited XOR is if you short-circuit something other than XOR and call it XOR by mistake.Virgy
F
0

NOTE: I know XOR and XNOR are bitwise operations, but considering the thing we are questioning here...

Ain't this work as conditional (boolean) XOR?

bool Xor(bool a, bool b){ return a != b }
a b x
False False False
False True True
True False True
True True False

Also I believe you can loop though data, aggregate them to use more than two operator. and still get the same result as Bitwise of Nth operand in same conditional manner

Foxtail answered 4/9, 2022 at 7:30 Comment(0)
P
-3

This question has been affectively answered, but I came across a different situation. It's true that there is no need for a conditional XOR. It's also true that the ^ operator can be used. However, if you need to only test the "true || false" status of the operands then ^ can lead to trouble. For example:

void Turn(int left, int right)
{
    if (left ^ right)
    {
        //success... turn the car left or right...
    }
    else
    {
        //error... no turn or both left AND right are set...
    }
}

In this example, if left is set to 10 (0xa) and right is set to 5 (0x5) the "success" branch is entered. For this (simplistic if silly) example, this would result in a bug since you shouldn't turn left AND right at the same time. What I gathered from the questioner is not that he actually wanted a conditional, but a simple way to perform the true/false on the values as passed to the xor.

A macro could do the trick:

#define my_xor(a, b) ( ((a)?1:0) ^ ((b)?1:0) )

Feel free to slap me around if I'm off the mark :o)

I read jimreed's answer below after I posted this (bad Yapdog!) and his is actually simpler. It would work and I have absolutely no idea why his answer was voted down...

Polygamy answered 20/8, 2012 at 23:8 Comment(1)
This is a C# question, not C/C++. if requires a Boolean expression, it won't even compile with an int.Soane

© 2022 - 2024 — McMap. All rights reserved.