346

有这样的事吗?这是我第一次遇到对它的实际需求,但我没有在 Stroustrup 中看到一个。我打算写:

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

但是没有^^运营商。我可以在^这里使用按位并得到正确的答案(不管机器表示真假)吗?我从不混合&and &&, or |and ||,所以我犹豫要不要和^and ^^

我会更自在地编写自己的bool XOR(bool,bool)函数。

4

11 回答 11

629

运算符为值!=服务于此目的。bool

于 2009-10-20T19:03:38.340 回答
287

对于真正的逻辑 XOR 操作,这将起作用:

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

请注意,!它们可以将值转换为布尔值并将它们取反,以便两个不相等的正整数(每个 a true)的计算结果为false

于 2009-10-20T20:04:41.343 回答
48

正确的手动逻辑XOR 实现取决于您希望通过 XOR 模拟其他逻辑运算符 (||&&) 的一般行为的程度。这些操作符有两点很重要:1)它们保证短路求值,2)它们引入了一个序列点,3)它们只对它们的操作数求值一次。

如您所知,XOR 评估不能短路,因为结果始终取决于两个操作数。所以1是没有问题的。但是2呢?如果您不关心 2,那么使用归一化(即bool)值运算符!=会根据结果执行 XOR 的工作。!如有必要,操作数可以很容易地用一元标准化。因此!A != !B在这方面实现了适当的 XOR。

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

a ? !b : b

||这实际上与制作与and的自制 XOR“相似”的方法非常接近&&。当然,这只有在您将 XOR 实现为宏时才有效。函数不会这样做,因为排序不适用于函数的参数。

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

++x > 1 && x < 5

在 C/C++ 中定义了行为和特定结果(至少在排序方面)。因此,人们可能会合理地期望用户定义的逻辑XOR 相同,如

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

!=基于 - 的 XOR 没有此属性。

于 2009-10-20T19:16:28.687 回答
26

还有另一种异或的方法:

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;
}
于 2012-10-07T12:17:38.610 回答
17

XOR 运算符不能短路;即,您不能仅通过评估其左侧操作数来预测 XOR 表达式的结果。因此,没有理由提供^^版本。

于 2009-10-20T19:02:53.973 回答
12

发布了一些比 !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
于 2012-09-06T02:46:47.877 回答
5

以下是我认为您在 C++ 中编写 XOR 比较的方式:

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);
于 2016-09-13T15:00:50.623 回答
5

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

第一部分是A OR B,即Inclusive OR;第二部分是,不是 A 和 B。一起得到 A 或 B,但不能同时得到 A 和 B。

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

|-----|-----|-----------|
|  A  |  B  |  A XOR B  |
|-----|-----|-----------|
|  T  |  T  |   False   |
|-----|-----|-----------|
|  T  |  F  |   True    |
|-----|-----|-----------|
|  F  |  T  |   True    |
|-----|-----|-----------|
|  F  |  F  |   False   |
|-----|-----|-----------|
于 2018-01-28T00:58:20.277 回答
5

使用一个简单的:

return ((op1 ? 1 : 0) ^ (op2 ? 1 : 0));
于 2015-07-29T08:33:01.970 回答
0

我使用“xor”(它似乎是一个关键字;在Code::Blocks中至少它变得粗体)就像您可以使用“and”而不是&&和“or”而不是||.

if (first xor second)...

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

于 2009-10-20T19:36:07.883 回答
-1
#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 (长度不同!)

于 2013-05-18T10:49:33.000 回答