c++中的逻辑异或运算符?

有这样的东西吗?这是我第一次遇到它的实际需求,但我没有看到一个列出在一种。我打算写:

// Detect when exactly one of A,B is equal to five.
return (A==5) ^^ (B==5);

但是没有^^操作符。我可以在这里使用按位^并得到正确答案(不管机器表示的真和假)吗?我从来没有混合&&&,或|||,所以我犹豫这样做与^^^

我更愿意写自己的bool XOR(bool,bool)函数。

414009 次浏览

异或运算符不能短路;也就是说,你不能仅仅通过计算一个XOR表达式的左操作数来预测它的结果。因此,没有理由提供^^版本。

!=操作符用于bool值。

正确的手动逻辑异或实现取决于你想用你的异或来模拟其他逻辑运算符(||&&)的一般行为的程度。关于这些操作符有两个重要的事情:1)它们保证短路计算,2)它们引入序列点,3)它们只计算操作数一次。

正如您所理解的,异或求值不能被短路,因为结果总是取决于两个操作数。所以1是不可能的。那么2呢?如果你不关心2,那么对于规范化(即bool)值,操作符!=根据结果完成XOR的工作。如果需要,操作数可以很容易地用一元!规范化。因此!A != !B在这方面实现了适当的XOR。

但如果你关心额外的序列点,!=和按位^都不是实现XOR的正确方法。正确执行异或(a, b)的一种可能方法如下所示

a ? !b : b

这实际上是最接近于你可以做一个自制的异或“类似”||&&。当然,这只有在将XOR作为宏实现时才会起作用。函数不会这样做,因为排序将不适用于函数的参数。

有人可能会说,在每个&&||处都有一个序列点的唯一原因是为了支持短路求值,因此XOR不需要。实际上,这是有道理的。然而,考虑一个中间有序列点的异或是值得的。例如,下面的表达式

++x > 1 && x < 5

已经在C/ c++中定义了行为和特定的结果(至少在排序方面)。因此,可以合理地期望用户定义的逻辑 XOR具有相同的值,例如

XOR(++x > 1, x < 5)

而基于__abc0的XOR没有这个属性。

我使用“xor”(它似乎是一个关键字;在块代码:中,至少它变得粗体),就像你可以用“and”代替&&,用“or”代替||一样。

if (first xor second)...

是的,它是位的。对不起。

对于一个真正的逻辑异或操作,这将工作:

if(!A != !B) {
// code here
}

注意!是用来将值转换为布尔值并对其求反的,这样两个不等的正整数(每个是true)将计算为false

有一些好的代码比!a != !b更好地解决了这个问题

注意,我必须添加BOOL_DETAIL_OPEN/CLOSE,这样它才能在MSVC 2010上工作

/* From: http://groups.google.com/group/comp.std.c++/msg/2ff60fa87e8b6aeb


Proposed code    left-to-right?  sequence point?  bool args?  bool result?  ICE result?  Singular 'b'?
--------------   --------------  ---------------  ---------- ------------  -----------  -------------
a ^ b                  no              no             no          no           yes          yes
a != b                 no              no             no          no           yes          yes
(!a)!=(!b)             no              no             no          no           yes          yes
my_xor_func(a,b)       no              no             yes         yes          no           yes
a ? !b : b             yes             yes            no          no           yes          no
a ? !b : !!b           yes             yes            no          no           yes          no
[* see below]          yes             yes            yes         yes          yes          no
(( a bool_xor b ))     yes             yes            yes         yes          yes          yes


[* = a ? !static_cast<bool>(b) : static_cast<bool>(b)]


But what is this funny "(( a bool_xor b ))"? Well, you can create some
macros that allow you such a strange syntax. Note that the
double-brackets are part of the syntax and cannot be removed! The set of
three macros (plus two internal helper macros) also provides bool_and
and bool_or. That given, what is it good for? We have && and || already,
why do we need such a stupid syntax? Well, && and || can't guarantee
that the arguments are converted to bool and that you get a bool result.
Think "operator overloads". Here's how the macros look like:


Note: BOOL_DETAIL_OPEN/CLOSE added to make it work on MSVC 2010
*/


#define BOOL_DETAIL_AND_HELPER(x) static_cast<bool>(x):false
#define BOOL_DETAIL_XOR_HELPER(x) !static_cast<bool>(x):static_cast<bool>(x)


#define BOOL_DETAIL_OPEN (
#define BOOL_DETAIL_CLOSE )


#define bool_and BOOL_DETAIL_CLOSE ? BOOL_DETAIL_AND_HELPER BOOL_DETAIL_OPEN
#define bool_or BOOL_DETAIL_CLOSE ? true:static_cast<bool> BOOL_DETAIL_OPEN
#define bool_xor BOOL_DETAIL_CLOSE ? BOOL_DETAIL_XOR_HELPER BOOL_DETAIL_OPEN

异或还有另一种方式:

bool XOR(bool a, bool b)
{
return (a + b) % 2;
}

这显然可以通过以下方式来证明:

#include <iostream>


bool XOR(bool a, bool b)
{
return (a + b) % 2;
}


int main()
{
using namespace std;
cout << "XOR(true, true):\t" << XOR(true, true) << endl
<< "XOR(true, false):\t" << XOR(true, false) << endl
<< "XOR(false, true):\t" << XOR(false, true) << endl
<< "XOR(false, false):\t" << XOR(false, false) << endl
<< "XOR(0, 0):\t\t" << XOR(0, 0) << endl
<< "XOR(1, 0):\t\t" << XOR(1, 0) << endl
<< "XOR(5, 0):\t\t" << XOR(5, 0) << endl
<< "XOR(20, 0):\t\t" << XOR(20, 0) << endl
<< "XOR(6, 6):\t\t" << XOR(5, 5) << endl
<< "XOR(5, 6):\t\t" << XOR(5, 6) << endl
<< "XOR(1, 1):\t\t" << XOR(1, 1) << endl;
return 0;
}
#if defined(__OBJC__)
#define __bool BOOL
#include <stdbool.h>
#define __bool bool
#endif


static inline __bool xor(__bool a, __bool b)
{
return (!a && b) || (a && !b);
}

它按定义工作。条件是用来检测你是否正在使用objective - c,它要求BOOL而不是BOOL(长度不同!)

使用简单的:

return ((op1 ? 1 : 0) ^ (op2 ? 1 : 0));

以下是我认为在c++中如何编写异或比较的方法:

bool a = true;   // Test by changing to true or false
bool b = false;  // Test by changing to true or false
if (a == !b)     // THIS IS YOUR XOR comparison
{
// do whatever
}

证明

XOR TABLE
a   b  XOR
--- --- ---
T   T   F
T   F   T
F   T   T
F   F   F


a == !b TABLE
a   b  !b  a == !b
--- --- --- -------
T   T   F     F
T   F   T     T
F   T   F     T
F   F   T     F

证明是,对输入和输出的详尽研究表明,在两个表中,对于每个输入集,两个表中的结果总是相同的。

因此,最初的问题是如何写:

return (A==5) ^^ (B==5)

答案是

return (A==5) == !(B==5);

如果你喜欢,也可以写下来

return !(A==5) == (B==5);

(A || B) && !(A && B)

第一部分是A或B,即包含或;第二部分是,不是A和B,合在一起你得到A或B,但不是A和B都有。

这将提供在下面的真值表中证明的异或。

|-----|-----|-----------|
|  A  |  B  |  A XOR B  |
|-----|-----|-----------|
|  T  |  T  |   False   |
|-----|-----|-----------|
|  T  |  F  |   True    |
|-----|-----|-----------|
|  F  |  T  |   True    |
|-----|-----|-----------|
|  F  |  F  |   False   |
|-----|-----|-----------|