条件付きXOR?


87

XORなぜC#に条件演算子がないのですか?

例:

true  xor false = true
true  xor true  = false
false xor false = false

15
!=代替としてどのように機能しますか?
パスカルキュオック2011年

45
C#にxor演算子(x ^ y)があります。したがって、私はその質問の前提を否定します。C#にxor演算子がないと信じた理由を説明できますか?なぜ人々がC#について間違ったことを信じているのかを知りたいです。
エリックリペット2011年

3
@Eric Lippert:彼は論理演算子(& | ^)と条件演算子(&& ||)を参照していると思います。しかし、その通りです(もちろん)、論理XORがあります
...– BoltClock

14
@BoltClock:ああ、質問が「なぜ短絡xor演算子がないのですか?」-どうしてあるのでしょうか?「and」を使用すると、最初の引数がfalseの場合、2番目の引数を評価する必要はありません。「または」を使用すると、最初の引数がtrueの場合、2番目の引数を評価する必要はありません。xorの両方の引数を常に評価する必要があるため、短絡は発生しません。
エリックリペット2011年

4
質問自体はMicrosoftに適したものであり、それが反対票を投じる正当な理由ですが、^演算子のために反対票を投じた人がいる場合は、質問が条件付きであるか、条件付きであるため、詳細に注意を払って読む必要があります。論理的であり、単に「なぜXORがないのか」ではありません。
邪悪なグリーボ2011年

回答:


121

C#では、条件演算子は必要な場合にのみ2次オペランドを実行します。

XOR定義上両方の値をテストする必要があるため、条件付きバージョンはばかげています。

  • 論理積:&-毎回両側をテストします。

  • 論理OR:|-毎回両側をテストします。

  • 条件付きAND:-1&&番目の側が真の場合にのみ2番目の側をテストします。

  • 条件付きOR:-1||番目の側がfalseの場合にのみ、2番目の側をテストします。


35
XOR演算子は、「条件演算子は必要な場合にのみ2次オペランドを実行する」という規則に違反しません。それは常に必要です。
Nathan Kovner 2015

2
条件付きXORは、特定のパターンの優れたエレガントなショートカットになる可能性がありますが、言語に含めるのに十分な理由があるかどうかはわかりません。XORが役立つ可能性があるこのようなパターンの例は、条件付き否定です。2番目のブール式が与えられた場合に、ブール式を否定する必要があるかどうか。
サルバドールゴメス

1
しばらくの間これに応答していませんが、@ KhyadHaldaによる人気のあるコメントに応答するために:なぜあなたは決して使用されないことがわかっている何かを構築するのですか?意図的にデッドコードを記述していることになります。
邪悪なグリーボ2017年

条件付きXOR演算子は、定義した規則(Khyadのコメント)に違反しないことと、場合によっては実際に役立つという事実と相まって、そのような演算子が存在することに起因する「愚かさ」をほとんど否定します。
Syndog 2017年

1
条件付きXORはどのように役立つでしょうか?条件付きXORは、両側を比較して、それらが等しいか等しくないかを判断せずに評価することはできません。2つのブール値を比較する条件付きXORの概念でさえ、各ブール値の値をチェックし、同等性をテストする必要があります。
邪悪なグリーボ2017年

280

質問は少し時代遅れですが...

この演算子は次のように機能します。

true xor false = true
true xor true = false
false xor true = true
false xor false = false

これは、!=演算子がブール型でどのように機能するかです。

(true != false) // true
(true != true) // false
(false != true) // true
(false != false) // false

ご覧のとおり^^、存在しないものを既存のものに置き換えることができます!=


46
これは実際、質問に直接かつ正確に対処する唯一の答えです。
usr

39
私はここに座って、これでうまくいくとは思っていなかったの!=です。
AdamMc331 2015

1
答えは正しいですが、コメントは正しくありません。「C#に条件付きXORがないのはなぜですか?」という質問には対応していません。厳密に言えば、これは論理演算子ではなく、リレーショナル等式演算子です。結果はXORと同じですが、クラスが異なります。2つのブール値をテストする場合にのみXORと比較され、演算子の両側を評価する必要があります。
邪悪なグリーボ2017年

3
@ TheEvilGreebo-あなたの言うことは本当です。!=演算子は、技術的には条件付きXOR演算子ではありません。ただし、この回答は事実上、「!=演算子が存在するため、条件付きXOR演算子は存在しません」と述べています。とにかく、それは私がそれを読む方法です。
Syndog 2017年

6
この投稿にたどり着いたほとんどすべての人が、実際にはブール値でXORを書きたいと思っていたと思います。論理的であるようにANDORしかし何もありませんXOR。または少なくとも私たちは気づいていませんでした!=:)@ TheEvilGreebo
M.kazem Akhgary 2017

30

論理XOR演算子があります: ^

ドキュメント:C#演算子^演算子


2
論理的であり、条件付きではありません。論理積=&、条件付きおよび= &&。彼は条件付きについて尋ねています。
邪悪なグリーボ2011年

3
これはバイナリであり、論理的ではありません。これは、boolが0または1のいずれかであると想定していますが、これはCLRでは当てはまりません。
usr

1
申し訳ありませんが、この回答は実際にはCONDITIONAL演算子に関する質問には回答していません。これは少し操作者です
Nathan Tregillus 2017

2
ちなみに、この回答にリンクされているドキュメント^には、ブールオペランドとともに使用すると、ブール演算子であることが明示的に記載されています。"boolオペランドの場合、^演算子は不等式演算子!="と同じ結果を計算します。整数のオペランドをビット単位でxorすることもできます^。C#はCではない
15ee8f99-57ff-4f92-890c-b56153

24

明確化と同様に、^演算子は整数型とブール値の両方で機能します。

MSDNの^演算子(C#リファレンス)を参照してください:

二項^演算子は、整数型とブール値に対して事前定義されています。整数型の場合、^はそのオペランドのビット単位の排他的論理和を計算します。ブールオペランドの場合、^はそのオペランドの論理排他的論理和を計算します。つまり、そのオペランドの1つだけが真である場合にのみ、結果は真になります。

たぶん、この質問がされた2011年以降、ドキュメントが変更されています。


2
長い間C#でプログラミングしてきましたが、これを知りませんでした。ありがとう@RichardCL!
Nathan Tregillus 2017

これは良い情報ですが、これに言及し^、5年前にある他の回答へのコメントまたは編集としてより適切であるように思われます。何かが変わったとは思えません。
クリス

13

Mark Lからの質問によると、正しいバージョンは次のとおりです。

 Func<bool, bool, bool> XOR = (X,Y) => ((!X) && Y) || (X && (!Y));

これが真理値表です:

 X | Y | Result
 ==============
 0 | 0 | 0
 1 | 0 | 1
 0 | 1 | 1
 1 | 1 | 0

参照: 排他的論理和


2
尋ねられた質問は、なぜC#に条件付きXOR演算子がないのかということでした。これは質問に答えません。関数自体に関して:この関数は条件付きXORとして動作しますが、問題は、非条件付きXORよりも効率的ですか?排他的論理和をテストするために、XORは1つだけの結果が真であることを確認する必要があります。これは、双方を評価して比較する必要があることを意味します。上記の関数は、少なくとも1つの値を反転しながら、条件の両側をテストします。これがXORと異なるかどうかを内部的に知っていますか?
邪悪なグリーボ2017年

6

そうそう、そうです。

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

1
これは二項演算子であり、論理演算子ではありません。これは、boolが0または1であると想定していますが、これはCLRでは当てはまりません。したがって、このコードは実際には機能しない可能性があります。
usr

6
@ usr、C#では、^演算子は2つのブールオペランドに適用されると論理的です。あなたはこれらの答えを通して非常に多くのコメントをしました、あなたはあなたの仮説をテストするために何かコードを実行したことがありますか?
マークL.

2
@MarcL。私がやったこと:pastebin.com/U7vqpn6G trueを出力しますが、true ^ trueはfalseであると想定されています。boolは常に0または1に等しいとは限りません。CLRの論理型ではありません。任意の内容の8ビット量です。問題を実証するために検証可能なILを生成することもできました。
usr

2
たとえば、C#以外のCLR言語を使用する場合。繰り返しますが、ILASMを使用して、これを行う完全に検証可能で安全なアセンブリを作成することもできます(ILレベルでは、ブール値はi1バイトと同じように、です)。これは100%定義され、安全に管理された動作です。CLRは大まかなものではありません。この動作を最初に見たのは、MicrosoftPexを使用したときでした。
usr

1
@EdPlunkett、あなたのトラックは私と一緒にいないと思います。usrは、内部的には実際には二項演算子であることを示しました。私が不満を言った「虐待」は、彼がそれを証明した手段でしたが、私はまだそれを維持しています。発生する可能性はありますが、ブール値の使用を無人地帯に徹底的に適用するため、ブール値をCLRセーフとして展開することは、せいぜい危険であり、最悪の場合は悪用(悪意がない場合)であり、バグとして扱う必要があります。usrが証明しているのは、内部的にC#は私たちのどちらかが思っていたよりもCに似ているということです。これを行うコードが有効であると見なされるべきかどうかは別の問題です。
マーク

4

条件付きxorは存在しませんが、xorはブール値に対して定義されており、すべての条件付き比較はブール値に評価されるため、論理論理和を使用できます。

したがって、次のように言うことができます。

if ( (a == b) ^ (c == d))
{

}

これは二項演算子であり、論理演算子ではありません。これは、boolが0または1であると想定していますが、これはCLRでは当てはまりません。したがって、このコードは実際には機能しない可能性があります。
usr

@usr CLRとはどういう意味ですか?これは私にとってはうまくいきましたが、ここでエッジケースを見逃したかどうかは
わかり

3
@Spencevailおそらく、偽でないブール値が整数表現を持たない可能性があるというケースについては考えていませんでした1。これはほとんど知られていない事実です。2つの偽でないブール値のxorがまだ偽でない状況になる可能性があります。つまり、この特定のコードでは、xor演算子は[0,1]の値にのみ適用されるため、私のコメントは(完全には)適用されません。
usr

1
@Spencevailは、まさに失敗する可能性のあるケースです。バイトを同じビットのブール値に変換する安全なマネージコード関数CreateBool(byte)を作成することができます。次に、CreateBool(1)^ CreateBool(2)はtrueですが、CreateBool(1)はtrueであり、CreateBool(2)もtrueです。&また、脆弱です。
usr

1
実は、RyuJITのバグを報告したのは、この可能性を考慮せず、コンパイルミスの&&ようにコンパイルし&たからです。
usr

3

あるが論理XOR演算子は^、全く存在しない条件付きのXOR演算子。以下を使用して、2つの値AとBの条件付きxorを実現できます。

A ? (!B) : B

両親は必要ありませんが、わかりやすくするために追加しました。

The Evil Greeboが指摘しているように、これは両方の式を評価しますが、xorをandorのように短絡させることはできません。


論理学者^と条件付き^の違いは何ですか?オブジェクト指向
アーメンTsirunyan

@Armen Tsirunyan論理演算子は、条件演算子がブール値を操作してブール結果を返す一方で、それが理にかなっている型でビット単位の演算を実行します。ブール値の考慮:0101 ^ 0011値は0110。です。
jimreed 2011年

3
いいえ、あなたは完全に間違っています。C#には両方のタイプのXORがあります(それぞれビット単位および論理と呼ばれます)。どちらも^記号を使用します。
Armen Tsirunyan 2011年


0

条件付き(短絡)XORのようなものはありません。条件演算子は、最初の引数だけを見て最終的な結果を明確に伝える方法がある場合にのみ意味があります。XOR(および加算)には常に2つの引数が必要であるため、最初の引数の後で短絡する方法はありません。

A = trueがわかっている場合、(A XOR B)=!Bです。

A = falseがわかっている場合、(A XOR B)= Bです。

どちらの場合も、Aは知っているがBは知らない場合は、十分に知ることができません(A XORB)。答えを計算するには、常にAとBの両方の値を学習する必要があります。両方の値がなくてもXORを解決できるユースケースは文字通りありません。

XORには、定義上、次の4つのケースがあることに注意してください。

false xor true  = true
true  xor false = true
true  xor true  = false
false xor false = false

繰り返しますが、うまくいけば、最初の値を知っているだけでは、2番目の値も知らずに答えを得るのに十分ではないことが上記から明らかです。しかし、あなたの質問では、最初のケースを省略しました。代わりに必要な場合

false op true  = false (or DontCare)
true  op false = true
true  op true  = false
false op false = false

次に、条件付き操作を短絡することで、実際にそれを取得できます。

A && !B

しかし、それはXORではありません。


この回答には、上記の少なくとも1つの回答に含まれていないものは何も表示されていません。あなたの短絡可能なun-xorがOPが探していたものであるという兆候は見当たりません。彼は、適切なxorが必要であると想定した回答を受け入れたからです。
15ee8f99-57ff-4f92-890c-b561 5319年

私は文字通り、2番目の引数を評価せずにOPの要求された真理値表を生成できる、これまでに提案された唯一の答えです。
ケビン・ホルト

また、OPは条件付きXORがない理由を尋ねました。上記の回答は、XORが2つの引数を必要とするためであると正しく述べていますが、IMOは、XORが実際に2つの引数を必要とする理由を十分に説明していないようです。明らかにそうではないと感じますが、このページのさまざまなコメントから、XORの基本的な2つの議論がまだ完全な初心者に完全に説明されていないことが明らかでした。
ケビン・ホルト

1
あなたはそれに私を話しました。
15ee8f99-57ff-4f92-890c-b561 5319年

@Kevin Holt-論理XORは、条件の1つが真である必要があるが、両方が必要でない場合に意味があります。両方の条件を評価する必要があることは重要ではありません。短絡の問題は、パフォーマンスが重要なコードを処理するときにのみ心配する必要がある低レベルの詳細です(制御フローが遅い)。それから論理演算子を作成するとき、「排他的論理和」が何を意味するのかについてもっと気になります。つまり、ビット単位のバージョンのように(他の演算子のように)動作させるか、または排他的にします(必要な数の条件がありますが、真になるのは1つだけです)。
ソーナム

-3

この質問は感情的に答えられましたが、私は別の状況に遭遇しました。条件付きXORの必要がないのは事実です。^演算子を使用できることも事実です。ただし、オペランドの「true || false」ステータスのみをテストする必要がある場合、^は問題を引き起こす可能性があります。例えば:

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

この例では、左が10(0xa)に設定され、右が5(0x5)に設定されている場合、「成功」ブランチが入力されます。この(ばかげている場合は単純な)例では、左と右を同時に回してはならないため、バグが発生します。質問者から私が集めたのは、彼が実際に条件付きを望んでいたということではなく、xorに渡された値に対してtrue / falseを実行する簡単な方法です。

マクロはトリックを行うことができます:

#define my_xor(a, b) ( ((a)?1:0) ^ ((b)?1:0) )

私がマークから外れている場合は、遠慮なく私を叩いてください:o)

私がこれを投稿した後、私は以下のjimreedの答えを読みました(悪いYapdog!)、そして彼は実際にはもっと単純です。それはうまくいくでしょう、そして私は彼の答えがなぜ投票されなかったのか全く分かりません...


3
これはC#の質問であり、C / C ++ではありません。 ifブール式が必要です。intでコンパイルすることもできません。
マークL.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.