ブール値のチェックにxor演算子を使用することは良い習慣ですか?[閉まっている]


150

私は個人的のような排他的か^それは、その簡潔さのブールチェックのコンテキストで理にかなって、オペレータ。私は書く方がずっと好きです

if (boolean1 ^ boolean2)
{
  //do it
}

より

if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
  //do it
}

しかし、私はしばしば他の経験豊富なJava開発者(初心者だけでなく)から混乱した見た目になり、時にはそれをビット単位の操作にのみ使用する方法についてコメントします。

^オペレーターの使用に関するベストプラクティスに興味があります。

回答:


298

!=代わりに単純に使用できます。


36
「!の何が悪いのか」 bool1 ^ bool2 ^ bool3は、bool1 != bool2 != bool3
BlueRaja-Danny Pflughoeft

4
脳が痛い。では、!=は誤った結果を生む可能性があるのでしょうか?
vemv

27
@vemvは、s !=に対して正しい結果をもたらしますboolean(ただしBooleansに対してはそうではないので、注意してください)。ただし、必ずしもきれいであると(some != null) != (other != null)は限りません。たとえば、読みにくい場合 があります。明示的なブール値でパーツを抽出するか!=、別のメソッドでを抽出する必要があります。
ivant 2011

23
理由は次のとおりです:a ^ b=> "aまたはb両方でa != bはない"、=> "aはbと等しくない"。(@RobertGrantが言ったこと)。ほとんどの人間は、xorが何であるかを知っていれば、最初の方が簡単に理解できます(これは、コンピューティングの分野にいるかどうかを知るのにかなり役立ちます)
Harold R. Eason

2
@ HaroldR.Easonここで重要な問題:a != b=>「aはbと同一ではない」
Mario Reutter

27

私はあなたがあなた自身の質問に答えたと思います-人々から奇妙な見た目を得た場合、より明確なオプションを選ぶ方がおそらく安全です。

コメントする必要がある場合は、おそらくより詳細なバージョンに置き換えて、そもそも人々に質問をさせない方がよいでしょう。


6
断言できますが(boolean1 && !boolean2) || (boolean2 && !boolean1)、実際のアプリケーションコードを真剣に書くと、奇妙な見た目になります…
Holger

17

似たような会話がたくさんあることがわかりました。一方で、目標を達成するためのコンパクトで効率的な方法があります。一方、チームの他のメンバーが理解できない可能性があり、将来のメンテナンスが困難になります。

私の一般的なルールは、使用されているテクニックがプログラマーに一般的に知っていることを期待することが合理的であるかどうか尋ねることです。この場合、プログラマーがブール演算子の使用方法を知っていることを期待するのは妥当だと思うので、ifステートメントでxorを使用してもかまいません。

大丈夫ではないものの例として、一時的な変数を使用せずにxorを使用して2つの変数を交換する方法を考えます。これは、誰もが知っているとは思わないだろうトリックなので、コードレビューには合格しません。


14

コメントしていただければ大丈夫だと思います// ^ == XOR


10

あなたはいつもそれを関数にラップして詳細な名前を与えることができます:

public static boolean XOR(boolean A, boolean B) {
    return A ^ B;
}

しかし、^演算子が何であるかを知らない人にとっては、Googleにとってそれは非常に簡単です。一回目以降は覚えにくいことではありません。他の用途を求めたので、ビットマスキングにXORを使用するのが一般的です。

XORを使用して、3番目の一時変数を使用せずに2つの変数の値を交換することもできます

// Swap the values in A and B
A ^= B;
B ^= A;
A ^= B;

XORスワッピングに関連するStackoverflowの質問を次に示します


6

私は最近、職場のJavaScriptプロジェクトでxorを使用し、何が起こっているのかを説明するために7行のコメント追加しました。その文脈で、XORを使用するための正当化は、(用語の1つだったterm1しない2つのが、3つの値を取ることができ、以下の例において)undefinedtrueまたはfalse他のながら(term2)とすることができるtrue、またはfalseundefinedケースに追加のチェックを追加する必要があったはずですが、xorを使用すると、最初の項がブール値として最初に評価され、次のundefinedように扱われるため、次のようにすれば十分falseです。

if (term1 ^ term2) { ...

結局、それは少しやり過ぎでしたが、とにかく、イースターエッグのようにそこに留めておきたかったのです。


IMHOは、暗黙の変換に依存するのではなく、遭遇することが珍しい状況では、変換を明示的にすることをお勧めします。そして一般的に、「未定義をfalseとして扱わせる」ことは、どの言語でも疑わしい慣行です。Javaでトライステート値を使用していませんが、C#では、bool? a値を使用して明示的にtrue a == trueかどうかをテストできます。Javaでも同様の手法はありますか?C#では、2つのbool?値が与えられると、「nullをfalseとして扱う」はにつながり(a == true) ^ (b == true)ます。同等の式は(a == true) != (b == true)です。あなたはJavaで同様のことをすることができますか?
ToolmakerSteve

5
if((boolean1 && !boolean2) || (boolean2 && !boolean1)) 
{ 
  //do it 
} 

私見このコードは簡略化できます:

if(boolean1 != boolean2) 
{ 
  //do it 
} 

5

コードの明快さを念頭に置いて、私は、ブールチェックでXORを使用することは、XORビット演算子の一般的な使用法ではないと考えています。私の経験から、JavaのビットワイズXORは通常、マスクflag toggle動作の実装使用されます。

flags = flags ^ MASK;

Vipan Singlaによるこの記事では、使用例をさらに詳しく説明しています。

例のようにビットワイズXORを使用する必要がある場合は、それを使用する理由をコメントしてください。ビットワイズリテラシーのオーディエンスでさえ、なぜそれを使用しているのか理解するためにトラックに立ち寄る必要があるためです。


-1

「boolean1 ^ boolean2」という表現は、その簡潔さから個人的に好みます。

私があなたの状況(チームで働いている)だった場合、 "boolean1 ^ boolean2"ロジックを "isDifferent(boolean1、boolean2)"などの説明的な名前の関数にカプセル化することで妥協します。

たとえば、「boolean1 ^ boolean2」を使用する代わりに、次のように「isDifferent(boolean1、boolean2)」を呼び出します。

if (isDifferent(boolean1, boolean2))
{
  //do it
}

「isDifferent(boolean1、boolean2)」関数は次のようになります。

private boolean isDifferent(boolean1, boolean2)
{
    return boolean1 ^ boolean2;
}

もちろん、このソリューションでは、見かけ上無関係な関数呼び出しを使用する必要があり、それ自体がベストプラクティスの精査の対象となりますが、冗長な(そして醜い)式 "(boolean1 &&!boolean2)||(boolean2 &&!boolean1)は回避されます。 「!


-2

使用パターンがそれを正当化するなら、なぜそうしないのですか?あなたのチームはオペレーターをすぐには認識しませんが、時間の経過とともに認識します。人間は常に新しい言葉を学びます。なぜプログラミングではないのですか?

私が述べるかもしれない唯一の注意は、 "^"には2番目のブール値チェックの短絡セマンティクスがないことです。短絡セマンティクスが本当に必要な場合は、静的なutilメソッドも機能します。

public static boolean xor(boolean a, boolean b) {
    return (a && !b) || (b && !a);
}

16
xorで短絡が発生する可能性はありません。結果を評価するには、aとbの両方を知っている必要があります。
セレマ

7
また、引数は呼び出し時に評価されるため、短絡は発生しません。
erikkallen 2009年

3
さらに、xorはマシンレベルで単一の操作である必要があります。
Ogre Psalm33 2013年

おそらく、短絡評価と遅延評価の違いを調べる必要があります。ショートサーキット評価は、ゼロ除算などの実行時エラーを引き起こす呼び出しを防ぐコードスタイルです。Cでは、これは「if(分母!= 0 &&分子/分母)」にすることができます。これは、ゼロ評価による除算を防ぐために遅延評価を利用します。あなたの答えも純粋に推測です。
マーティン

2
正直に言うと、プログラマは関数を書いています xorに言うと、xor演算子とまったく同じようにするプログラマは、使用したばかりのプログラマよりも(特に能力に関して)疑問を抱き^ます。
Stijn de Witt 2017

-3

!=は2つの変数を比較しても問題ありません。ただし、複数の比較では機能しません。


-3

ビット単位の演算子として、xorは他のどの手段よりもはるかに高速です。したがって、パフォーマンスが重要でスケーラブルな計算には、xorが不可欠です。

私の主観的な個人的な意見:ブール値に等号(==または!=)を使用することは、いかなる目的でも絶対に禁止されています。それを使用すると、基本的なプログラミングの倫理と基礎の欠如を示しています。^で混乱した見た目を与える人は、ブール代数の基本に送り返されるべきです(ここに「信念の川へ」と書きたくなりました:))。


1
JITは、あるブール式を別のブール式に置き換えるなど、キーホール(小さな)最適化に非常に優れている点を除きます。
David Leppik

1
また、^は主にブール(論理)演算子ではなく、ビットごとの演算子です。標識のバグが存在する可能性が高いため、速度を落とすようにリーダーに指示します。^を!=に使用すると、Cでプログラミングした場合、本当に混乱することになります。ビットごとの演算子は、リーダー(コードをデバッグしている人)に信号を送り、速度を落とし、符号エラーを探します。 。そして、それらは扱いにくい場合があります。たとえば、Javaの%がCやPythonのように真のモジュロではないことを知っていますか?C、JavaScript、Pythonで同じように動作するコードのスニペットがありましたが、Javaでは動作しませんでした。
David Leppik

6
これはどうして賛成されたのですか?まず、Javaでは、XORと!=が[ 完全に同じコードに] [ stackoverflow.com/a/4175512/202504]でコンパイルされます。次に、アセンブラーの等価性とxorのテストでも、それぞれ1つの単純な操作です。ステートメントを裏付ける数字はありますか?
jmiserez 2013年

-4
str.contains("!=") ^ str.startsWith("not(")

私よりよく見える

str.contains("!=") != str.startsWith("not(")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.