簡體   English   中英

C ++中的邏輯異或運算符?

[英]Logical XOR operator in C++?

有這樣的事情嗎? 這是我第一次遇到實際需求,但我沒有看到Stroustrup 中列出 的需求 我打算寫:

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

但是沒有^^運算符。 我可以在這里使用按位^並得到正確答案(無論真假的機器表示如何)? 我從不混合&&& ,或| || ,所以我猶豫要不要使用^^^

我會更舒服地編寫自己的bool XOR(bool,bool)函數。

!=運算符用於bool值。

對於真正的邏輯異或運算,這將起作用:

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

注意! 在那里將值轉換為布爾值並否定它們,以便兩個不相等的正整數(每個都是true )評估為false

正確的手動邏輯XOR 實現取決於您想用 XOR 模擬其他邏輯運算符( ||&& )的一般行為的程度。 關於這些運算符有兩個重要的事情:1)它們保證短路評估,2)它們引入了一個序列點,3)它們只評估它們的操作數一次。

如您所知,XOR 評估不能短路,因為結果始終取決於兩個操作數。 所以1是沒有問題的。 但是2呢? 如果您不關心 2,那么使用規范化(即bool )值運算符!=就結果而言執行 XOR 的工作。 操作數可以很容易地用一元歸一化! ,如有必要。 因此!A != !B在這方面實現了正確的 XOR。

但是,如果您關心額外的序列點,則!=和按位^都不是實現 XOR 的正確方法。 正確執行 XOR(a, b) 的一種可能方法可能如下所示

a ? !b : b

這實際上與制作與|| “相似”的自制 XOR 非常接近&& 當然,這只有在您將 XOR 實現為宏時才有效。 函數不會這樣做,因為排序不適用於函數的參數。

有人可能會說,在每個&&||處都有一個序列點的唯一原因是為了支持短路評估,因此 XOR 不需要一個。 這實際上是有道理的。 然而,值得考慮在中間有一個序列點的異或。 例如,下面的表達式

++x > 1 && x < 5

在 C/C++ 中定義了行為和特定結果(至少在排序方面)。 因此,人們可能會合理地期望用戶定義的邏輯XOR 會得到相同的結果,如

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

而基於!=的 XOR 沒有這個屬性。

還有另一種方式進行異或:

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;
}

XOR 運算符不能短路; 即您不能僅通過評估其左手操作數來預測 XOR 表達式的結果。 因此,沒有理由提供^^版本。

發布了一些很好的代碼,比 !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

使用一個簡單的:

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

以下是我認為您在 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);

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

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

這將提供在下面的真值表中證明的異或。

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

我使用“xor”(它似乎是一個關鍵字;在Code::Blocks中至少它變得粗體)就像您可以使用“and”代替&&和“or”代替|| .

if (first xor second)...

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

#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 (長度不同!)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM