そんなことありますか?それが実際的な必要性に遭遇したのは今回が初めてですが、リストに載っているものは見当たりません Stroustrupでは 。私は書くつもりです:
// Detect when exactly one of A,B is equal to five.
return (A==5) ^^ (B==5);
しかし^^
演算子はありません。ここでビットごとの^
を使って正しい答えを得ることはできますか(機械表現のtrueとfalseに関係なく)。 &
と&&
、または|
と||
を混ぜることは絶対にありませんので、^
と^^
を一緒に使用することを躊躇します。
代わりに自分自身のbool XOR(bool,bool)
関数を書くほうが楽です。
!=
演算子は、この目的をbool
値に使用します。
真の論理XOR操作の場合、これは機能します。
if(!A != !B) {
// code here
}
適切なマニュアルlogical XORの実装は、他の論理演算子(||
と&&
)の一般的な振る舞いをXORでどれだけ厳密に模倣したいかによって異なります。これらの演算子には2つの重要なことがあります。1)短絡評価を保証すること、2)シーケンスポイントを導入すること、3)オペランドを一度だけ評価することです。
XOR評価は、ご存知のとおり、結果は常に両方のオペランドに依存するため、短絡することはできません。だから1は問題外です。しかし、2はどうですか? 2を気にしないのであれば、正規化された(つまりbool
)値を使って、演算子!=
は結果に関してXORの仕事をします。そして必要ならば、オペランドは単項!
で簡単に正規化できます。したがって!A != !B
はその点で適切なXORを実装します。
しかし、余分なシーケンスポイントを気にするのであれば、!=
もビット単位の^
もXORを実装するための適切な方法ではありません。 XOR(a、b)を正しく実行する方法の1つは、次のようになります。
a ? !b : b
これは実際には、手作りのXORを||
や&&
に「似た」ものにするのと同じくらい近いです。これは、XORをマクロとして実装した場合にのみ有効です。順序付けは関数の引数には適用されないため、関数は機能しません。
しかし、&&
と||
のそれぞれにシーケンスポイントを持つ唯一の理由は、短絡評価をサポートすることであり、したがってXORはそれを必要としない、と誰かが言うかもしれません。これは実際には意味があります。それでも、途中にシーケンスポイントを持つXORを持つことを検討する価値があります。たとえば、次の式
++x > 1 && x < 5
c/C++における振る舞いと具体的な結果を定義しています(少なくとも順序付けに関して)。したがって、次のように、ユーザー定義の論理 XORから同じことが合理的に予想される場合があります。
XOR(++x > 1, x < 5)
!=
ベースのXORにはこのプロパティはありません。
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よりも優れた問題を解決するための優れたコードがいくつか投稿されています。
MSVC 2010で機能するように、BOOL_DETAIL_OPEN/CLOSEを追加する必要がありました。
/* 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
その証拠は、入力と出力の徹底的な研究は、2つの表では、すべての入力集合に対して結果が2つの表で常に同一であることを示しています。
したがって、元の質問は、次のように書く方法です。
return (A==5) ^^ (B==5)
答えは
return (A==5) == !(B==5);
またはあなたが好きなら、書く
return !(A==5) == (B==5);
(A || B) && !(A && B)
最初の部分はA OR Bです。これは包含ORです。 2番目の部分は、AとBではなく、一緒にAまたはBになりますが、AとBの両方にはなりません。
これは以下の真理値表で証明されたXORを提供します。
|-----|-----|-----------|
| A | B | A XOR B |
|-----|-----|-----------|
| T | T | False |
|-----|-----|-----------|
| T | F | True |
|-----|-----|-----------|
| F | T | True |
|-----|-----|-----------|
| F | F | False |
|-----|-----|-----------|
&&
や||
の代わりにandを使用できるのと同じように、 "xor"(これはキーワードのようです。少なくとも Code :: Blocks 太字になっています)を使用します。
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を要求しています(長さは異なります!)