条件异或?

为什么 C # 没有条件 XOR运算符?

例如:

true  xor false = true
true  xor true  = false
false xor false = false
92770 次浏览

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 ^.

Oh yes, it does.

bool b1 = true;
bool b2 = false;
bool XOR = b1 ^ b2;

you can use:

a = b ^ c;

just like in c/c++

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.

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))
{


}

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.

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...

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 !=.

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

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.

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.

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