Javaで「論理排他OR」演算子を作成する


274

観察:

Javaには論理AND演算子があります。
Javaには論理OR演算子があります。
Javaには論理NOT演算子があります。

問題:

Sunによると、Javaには論理XOR演算子はありません。一つ定義したいと思います。

メソッド定義:

メソッドとしては、次のように簡単に定義されます。

public static boolean logicalXOR(boolean x, boolean y) {
    return ( ( x || y ) && ! ( x && y ) );
}


メソッド呼び出し:

このメソッドは次の方法で呼び出されます。

boolean myVal = logicalXOR(x, y);


オペレーターの使用:

むしろ、次のように使用される演算子が必要です。

boolean myVal = x ^^ y;


質問:

Javaで新しい演算子を定義する方法について何も見つかりません。どこから始めればいいですか?


1
何?あなたが与えたリンクには「ビット単位の排他的OR」というコンテンツがあります
Mathew P. Jones

C ++のようにJavaで演算子を定義できるかどうか疑問に思っていましたか?
avgvstvs 2015年

1
&と&&の違いを誤解しているようです。どちらも(ブール値の)論理演算子です。スターブルーの答えはそれをより広くカバーしています。
Vlasec

チュートリアルにないからといって、Javaにないという意味ではありません-チュートリアルは(常に)完了していません。Java言語仕様15.22.2を
user85421

5
それ!=はと呼ばれ、論理XNORと呼ばれる==
Mark K Cowan '12

回答:


695

Javaには論理XOR演算子があり^(のようにa ^ b)です。

それとは別に、Javaで新しい演算子を定義することはできません。

編集:ここに例があります:

public static void main(String[] args) {
    boolean[] all = { false, true };
    for (boolean a : all) {
        for (boolean b: all) {
            boolean c = a ^ b;
            System.out.println(a + " ^ " + b + " = " + c);
        }
    }
}

出力:

false ^ false = false
false ^ true = true
true ^ false = true
true ^ true = false

5
これは投稿を書いたときにも私の記憶を逃れましたが、^を論理演算子として(およびビットごとに)使用できると思います。
Neil Coffey

144
^はビット演算子だけではありません。これは論理演算子でもあります。^演算子がオーバーロードされています。整数型またはブール型で動作します。すばらしい答えjavashlookの+1。Eddie、それはJLSセクション15.22.2「ブール論理演算子&、^、および|」より明確になりません。
エリクソン2009

97
そしてもちろん、答えは&&と||です。式の2番目の部分と&および|の評価をスキップします 常に式の両方の部分を評価します(私のJLSの読み取りから)。^^は常に定義により常に両方の部分を評価する必要があるため、^と同じように動作します。たぶんない理由^^
エディ

81
@Eddie:それと^^は絵文字のように見えます。
マイケル・マイヤーズ

5
多分それは意味論の問題かもしれませんが、それがXORになると、ビットごとと論理的に同じ結果が得られます。したがって、別個の演算子は必要ありません。XOR演算子の単純化された真理値表はX ^!X = 1です。入力が異なるかどうかを判別する必要があるため、XORで入力を短絡することはできません。実際のXORゲートの製造を知っていれば、はるかに理解しやすくなります。
hfontanez 2015

305

x!= yではないですか?


5
xとyがブール値の場合、xorと!=の論理テーブルは同じになります。t、t => f; t、f => t; f、t => t; f、f => f
グレッグケース

81
モーリス:ああ、あなたはちょうど私の心を吹き飛ばした!どうしてこれに気づかなかったのですか?

8
@Milhousうまくいきa != b != cませんa ^ b ^ cか?その場合、あなたは間違っています。
fredoverflow 2014年

3
モーリス、素晴らしい!やらなければならないことがたくさんあると、単純なものを失ってしまうことがあります:)
sberezin

6
このアプローチは、両側がラッパークラスである場合に破綻しnew Boolean(true) != new Boolean(true)ますtrue
VlastimilOvčáčík2017年

74

Javaには論理AND演算子があります。
Javaには論理OR演算子があります。

違う。

Javaは

  • 2つの論理AND演算子:通常のANDは&であり、短絡ANDは&&であり、
  • 2つの論理OR演算子:通常のORは| そして短絡ORは||です。

XORは、短絡評価ができないため、^としてのみ存在します。


2
興味深いコメント。それは文書化されていますか?
user666412 2013年

1
と思います| それらはビットごとの演算子であるため、短絡ではありません。そして実際には、それらを短絡させることは不可能です。
KrzysztofJabłoński2013年

3
@KrzysztofJabłońskiこれらは数値のビット単位の演算子ですが、ここではブール式について説明しています。
starblue

3
@ user666412はい、Java言語仕様(他にありますか?)
starblue

18
2つのAND演算子と2つのOR演算子がある場合、「Javaには論理AND演算子があります」と「Javaには論理OR演算子があります」というステートメントは間違っていません。定義上、2つある場合、1つもあります。
RyanfaeScotland 2013年

31

おそらく、あなたは違いを誤解&して&&|および|| ショートカット事業者の目的&&||最初のオペランドの値が結果を決めることができ、第2オペランドは評価する必要がないように、ということです。

これは、2番目のオペランドがエラーになる場合に特に役立ちます。例えば

if (set == null || set.isEmpty())
// or
if (list != null && list.size() > 0)

ただし、XORでは、結果を取得するために常に第2オペランドを評価する必要があるため、意味のある演算はだけです^


20

あなただけ書くことができます (a!=b)

これはと同じように機能しa ^ bます。


9

これは、演算子のオーバーロードが意図的に言語から除外されているためです。それらは文字列連結で少し「だまされ」ましたが、それ以上に、そのような機能は存在しません。

(免責事項:私はJavaの過去2つのメジャーリリースで作業していないので、今であれば、非常に驚​​きます)


5
C ++でも新しい演算子を定義できないことに注意してください。できることは、古いものに新しい意味を与えることだけです。
David Thornley、

7

Javaでの唯一の演算子のオーバーロードは、文字列に対する+です(JLS 15.18.1文字列連結演算子+)。

コミュニティは長年にわたって3つに分かれており、1/3はそれを望まない、1/3はそれを望む、そして1/3は気にしない。

ユニコードを使用して、シンボルであるメソッド名を作成できます...したがって、使用したいシンボルがある場合は、myVal = x。$(y);を実行できます。ここで、$はシンボルであり、xはプリミティブではありません...しかし、一部のエディターではそれはおかしなことになり、プリミティブでは実行できないため制限があります。


7

次のコード:

public static boolean logicalXOR(boolean x, boolean y) {
    return ( ( x || y ) && ! ( x && y ) );
}

不必要です。

なぜ書かないのですか?

public static boolean logicalXOR(boolean x, boolean y) {
    return x != y;
}

また、javashlookが言ったように、すでに^演算子があります。

!=そして^ブールオペランド(お使いの場合)のために、しかし、異なる整数オペランドのために同一の*作業。

*注:
1.それらはboolean(プリミティブBoolean型)オペランドと同じように機能しますが、(オブジェクト型)オペランドでは機能しません。としてBoolean(オブジェクトタイプ)値はvalueを持つことができますnull。そして!=戻りますfalseまたはtrueそのオペランドの一方または両方である場合null、一方が^スローされますNullPointerException。この場合には。
2.これらは同じように機能しますが、優先順位が異なります。たとえば、&a & b != c & dと一緒に使用すると、として扱われa & (b != c) & d、(offtopic:ouch、Cスタイルの優先順位テーブルは)a & b ^ c & dとして扱われ(a & b) ^ (c & d)ます。


1
私が好きなブール値の場合!=
GKalnytskyi

1
Boolean値の@GKalnytskyiは!=正しく機能しません。以下のためbooleanの値それは大丈夫です。
vadipp 2017年

2
!=と^は、ブールオペランドに対して同じように機能しません。優先度が高いため、「false&false!= true」と「false&false ^ true」では異なる結果が得られます。
Albert Hendriks

1
@AlbertHendriksは、私はより良い彼らがいることを言うと思います仕事同様に、異なる持って順位を(それは用語の問題だが)。
サーシャ2017

6

これは、Javaのvar arg XORメソッドです...

public static boolean XOR(boolean... args) {
  boolean r = false;
  for (boolean b : args) {
    r = r ^ b;
  }
  return r;
}

楽しい


これは、非常に奇妙な動作をするように感じます。たとえばXOR(true,true,true)、trueを返しますが、これはと呼ばれるメソッドに期待するものとは異なりますXOR。私の予想される動作は、常にfalseを返すことです(これはもちろん役に立ちません)
Richard Tingle

5

論理的な排他的論理和はJavaで呼び出され!=ます。^友達を混乱させたい場合にも使えます。


2

Xtend(Infix演算子と演算子オーバーロード)を使用して、演算子をオーバーロードし、Javaにとどまることができます


Xtendではキャレットをオーバーライドできないことに注意してください^。使用する必要がありますbool_1.xor(bool_2)。奇妙なことに、パーサーではキャレットを使用することさえできません。xorブール値とbitwiseXor整数に使用する必要があります。もちろん、別の演算子をオーバーロードすることもできますが、それは非常に混乱します。
ケルビン

2

あなたが求めていることはあまり意味がありません。私が正しくない場合を除き、XORを使用してANDおよびORと同じ方法で論理演算を実行することをお勧めします。あなたの提供されたコードは実際に私が何を好んでいるかを示しています:

public static boolean logicalXOR(boolean x, boolean y) {
    return ( ( x || y ) && ! ( x && y ) );
}

関数にはブール値の入力があり、ブール値でビットごとのXORを使用すると、結果は指定したコードと同じになります。言い換えると、ビットごとのXORは、個々のビット(ブール値)を比較するとき、またはより大きな値の個々のビットを比較するときにすでに効率的です。これをコンテキストに入れると、バイナリ値に関しては、ゼロ以外の値はすべてTRUEになり、ZEROだけがfalseになります。

したがって、論理ANDが適用されるのと同じ方法でXORを適用するには、1ビットのみのバイナリ値(同じ結果と効率が得られる)を使用するか、バイナリ値をビットごとではなく全体として評価する必要があります。つまり、式(010 ^^ 110)= 100ではなく、(010 ^^ 110)= FALSEとなります。これにより、ほとんどの意味上の意味が操作から削除され、使用すべきではない論理テストを表します。


1

AとBは、真理値表が同じように見えるように、!=をxorと同じにするためにブール値にする必要があります。!(A == B)も使用できます。


1

私は非常に人気のあるクラス「org.apache.commons.lang.BooleanUtils」を使用しています

この方法は多くのユーザーによってテストされており、安全です。楽しんで。使用法:

boolean result =BooleanUtils.xor(new boolean[]{true,false});

0

ブールデータ型は整数のように格納されるので、ビット演算子^はブール値で使用するとXOR演算のように機能します。

//©Mfpl - XOR_Test.java

    public class XOR_Test {
        public static void main (String args[]) {
            boolean a,b;

            a=false; b=false;
            System.out.println("a=false; b=false;  ->  " + (a^b));

            a=false; b=true;
            System.out.println("a=false; b=true;  ->  " + (a^b));

            a=true;  b=false;
            System.out.println("a=true;  b=false;  ->  " + (a^b));

            a=true; b=true;
            System.out.println("a=true; b=true;  ->  " + (a^b));

            /*  output of this program:
                    a=false; b=false;  ->  false
                    a=false; b=true;  ->  true
                    a=true;  b=false;  ->  true
                    a=true; b=true;  ->  false
            */
        }
    }

0

次に例を示します。

2つのint値が与えられ、1つが負で1つが正の場合、trueを返します。パラメータ「negative」がtrueの場合を除いて、両方が負の場合のみtrueを返します。

    public boolean posNeg(int a, int b, boolean negative) {
      if(!negative){
        return (a>0 && b<0)^(b>0 && a<0);
      }
      else return (a<0 && b<0);
    }

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