Ist es empfehlenswert, den xor-Operator für boolesche Prüfungen zu verwenden? [geschlossen]


150

Ich persönlich mag die ausschließliche oder , ^, Bediener , wenn es Sinn im Zusammenhang mit boolean Kontrollen wegen seiner Prägnanz macht. Ich schreibe viel lieber

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

als

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

Aber ich bekomme oft verwirrte Blicke von anderen erfahrenen Java-Entwicklern (nicht nur von Neulingen) und manchmal Kommentare darüber, wie es nur für bitweise Operationen verwendet werden sollte.

Ich bin gespannt auf die Best Practices in Bezug auf die Verwendung des ^Betreibers.

Antworten:


298

Sie können !=stattdessen einfach verwenden .


36
"Was ist los mit! =" bool1 ^ bool2 ^ bool3bool1 != bool2 != bool3
Ist

4
Mein Gehirn schmerzt. Kann also! = Falsche Ergebnisse liefern oder nicht?
vemv

27
@vemv !=liefert korrekte Ergebnisse für booleans (aber nicht für Booleans, seien Sie also vorsichtig). Es ist jedoch nicht immer schön, zum Beispiel (some != null) != (other != null)nicht sehr lesbar. Sie müssen die Teile entweder in expliziten Booleschen Werten oder !=in einer separaten Methode extrahieren .
ivant

23
Hier ist der Grund: a ^ b=> "a oder b, aber nicht beide", a != b=> "a ist nicht gleich b". (Was @RobertGrant gesagt hat). Die meisten Menschen würden den ersten leichter verstehen, wenn sie wissen, was xor ist (was ziemlich nützlich ist, um zu wissen, ob Sie auf dem Gebiet des Rechnens sind ...)
Harold R. Eason

2
@ HaroldR.Eason wichtige Nitpicking hier: a != b=> "a ist nicht identisch mit b"
Mario Reutter

27

Ich denke, Sie haben Ihre eigene Frage beantwortet - wenn Sie seltsame Blicke von Menschen bekommen, ist es wahrscheinlich sicherer, die explizitere Option zu wählen.

Wenn Sie es kommentieren müssen, ist es wahrscheinlich besser, es durch die ausführlichere Version zu ersetzen und die Leute nicht dazu zu bringen, die Frage überhaupt zu stellen.


6
Ich kann Ihnen behaupten, Sie werden seltsame Blicke von mir bekommen, wenn Sie ernsthaft (boolean1 && !boolean2) || (boolean2 && !boolean1)in einen realen Anwendungscode schreiben ...
Holger

17

Ich finde, dass ich viele ähnliche Gespräche habe. Einerseits haben Sie eine kompakte, effiziente Methode, um Ihr Ziel zu erreichen. Auf der anderen Seite haben Sie etwas, das der Rest Ihres Teams möglicherweise nicht versteht, was es schwierig macht, es in Zukunft aufrechtzuerhalten.

Meine allgemeine Regel ist zu fragen, ob die verwendete Technik etwas ist, von dem man vernünftigerweise erwarten kann, dass Programmierer es im Allgemeinen wissen. In diesem Fall halte ich es für vernünftig, von Programmierern zu erwarten, dass sie wissen, wie man boolesche Operatoren verwendet. Daher ist die Verwendung von xor in einer if-Anweisung in Ordnung.

Nehmen Sie als Beispiel für etwas, das nicht in Ordnung wäre, den Trick, xor zu verwenden, um zwei Variablen ohne Verwendung einer temporären Variablen auszutauschen. Das ist ein Trick, mit dem ich nicht erwarten würde, dass jeder vertraut ist, also würde er die Codeüberprüfung nicht bestehen.


14

Ich denke, es wäre in Ordnung, wenn Sie es kommentieren würden, z // ^ == XOR.


10

Sie können es jederzeit in eine Funktion einschließen, um ihm einen ausführlichen Namen zu geben:

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

Aber es scheint mir, dass es für niemanden schwer sein würde, der nicht wusste, wofür der Operator ^ ist, es wirklich schnell zu googeln. Es wird nicht schwer sein, sich nach dem ersten Mal zu erinnern. Da Sie nach anderen Verwendungszwecken gefragt haben, ist es üblich, das XOR für die Bitmaskierung zu verwenden.

Sie können XOR auch verwenden, um die Werte in zwei Variablen auszutauschen, ohne eine dritte temporäre Variable zu verwenden .

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

Hier ist eine Stackoverflow-Frage zum XOR-Austausch .


6

Ich habe kürzlich ein xor in einem JavaScript-Projekt bei der Arbeit verwendet und am Ende 7 Kommentarzeilen hinzugefügt , um zu erklären, was los war. Die Begründung für die Verwendung von xor in diesem Zusammenhang war , dass eine der Bedingungen ( term1im Beispiel unten) konnte nicht zwei nimmt aber drei Werte: undefined, trueoder falsewährend der anderen ( term2) könnte sein , trueoder false. Ich hätte eine zusätzliche Prüfung für die undefinedFälle hinzufügen müssen, aber mit xor war Folgendes ausreichend, da das xor den ersten Term zwingt, zuerst als Boolescher Wert ausgewertet zu werden, und wie folgt undefinedbehandelt wird false:

if (term1 ^ term2) { ...

Am Ende war es ein bisschen übertrieben, aber ich wollte es trotzdem dort behalten, als eine Art Osterei.


IMHO ist es in einer ungewöhnlichen Situation besser, die Konvertierung explizit zu machen, anstatt sich auf implizite Konvertierung zu verlassen . Und im Allgemeinen ist es eine fragwürdige Praxis in jeder Sprache, "Undefiniertes als falsch behandeln zu lassen". Ich habe in Java keine Tri-State-Werte verwendet, aber in C # kann ein bool? aWert explizit auf true getestet werden. Gibt a == truees eine ähnliche Technik in Java? In C # würde bei zwei gegebenen bool?Werten "Null als falsch behandeln" dazu führen (a == true) ^ (b == true). Eine äquivalente Formel lautet (a == true) != (b == true). Kannst du etwas ähnliches in Java machen?
ToolmakerSteve

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

IMHO könnte dieser Code vereinfacht werden:

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

5

Im Hinblick auf die Klarheit des Codes bin ich der Meinung, dass die Verwendung von XOR bei booleschen Prüfungen keine typische Verwendung für den bitweisen XOR-Operator ist. Nach meiner Erfahrung wird bitweises XOR in Java normalerweise verwendet, um ein Maskenverhalten zu implementieren flag toggle:

flags = flags ^ MASK;

Dieser Artikel von Vipan Singla erklärt den Anwendungsfall ausführlicher.

Wenn Sie bitweises XOR wie in Ihrem Beispiel verwenden müssen, kommentieren Sie, warum Sie es verwenden, da wahrscheinlich sogar ein bitweises Publikum in seinen Tracks anhalten muss, um zu verstehen, warum Sie es verwenden.


-1

Ich persönlich bevorzuge den Ausdruck "boolean1 ^ boolean2" wegen seiner Prägnanz.

Wenn ich in Ihrer Situation wäre (in einem Team arbeiten), würde ich einen Kompromiss eingehen, indem ich die Logik "boolean1 ^ boolean2" in eine Funktion mit einem beschreibenden Namen wie "isDifferent (boolean1, boolean2)" kapsle.

Anstatt beispielsweise "boolean1 ^ boolean2" zu verwenden, würden Sie "isDifferent (boolean1, boolean2)" wie folgt aufrufen:

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

Ihre Funktion "isDifferent (boolean1, boolean2)" würde folgendermaßen aussehen:

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

Natürlich beinhaltet diese Lösung die Verwendung eines scheinbar fremden Funktionsaufrufs, der an sich der Best Practices-Prüfung unterliegt, aber den ausführlichen (und hässlichen) Ausdruck "(boolean1 &&! Boolean2) || (boolean2 &&! Boolean1) vermeidet. "!


-2

Wenn das Verwendungsmuster dies rechtfertigt, warum nicht? Während Ihr Team den Bediener nicht sofort erkennt, könnte es mit der Zeit. Menschen lernen ständig neue Wörter. Warum nicht in der Programmierung?

Die einzige Warnung, die ich sagen könnte, ist, dass "^" nicht die Kurzschlusssemantik Ihrer zweiten booleschen Prüfung hat. Wenn Sie die Kurzschlusssemantik wirklich benötigen, funktioniert auch eine statische util-Methode.

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

16
Ich sehe keinen Kurzschluss mit xor - Sie müssen sowohl a als auch b kennen, um das Ergebnis zu bewerten.
Thelema

7
Außerdem würden die Argumente zum Zeitpunkt des Aufrufs ausgewertet, sodass keinerlei Kurzschlüsse auftreten.
Erikkallen

3
Außerdem sollte xor eine einzelne Operation auf Maschinenebene sein.
Oger Psalm33

Sie sollten wahrscheinlich den Unterschied zwischen Kurzschlussauswertung und verzögerter Auswertung nachschlagen. Die Kurzschlussauswertung ist ein Codestil, der Aufrufe verhindert, die andernfalls zu Laufzeitfehlern führen würden, z. B. Division durch Null. In C kann dies ´if (Nenner! = 0 && Zähler / Nenner) ´ sein, das selbst eine verzögerte Auswertung verwendet, um eine Division durch Null zu verhindern. Ihre Antwort ist auch rein spekulativ.
Martin

2
Um ehrlich zu sein, würde ein Programmierer, der eine Funktion schreibt xor, die genau das tut, was der xor-Operator tut, aber auf Umwegen, mehr Fragen in meinem Kopf aufwerfen (insbesondere über Kompetenz) als ein Programmierer, der gerade verwendet hat ^.
Stijn de Witt

-3

! = ist OK, um zwei Variablen zu vergleichen. Bei mehreren Vergleichen funktioniert dies jedoch nicht.


-3

Als bitweiser Operator ist xor viel schneller als jedes andere Mittel, um es zu ersetzen. Für leistungskritische und skalierbare Berechnungen ist xor daher unerlässlich.

Meine subjektive persönliche Meinung: Es ist für jeden Zweck absolut verboten, Gleichheit (== oder! =) Für Boolesche Werte zu verwenden. Die Verwendung zeigt einen Mangel an grundlegender Programmierethik und Grundlagen. Jeder, der Sie verwirrt ansieht, sollte zu den Grundlagen der Booleschen Algebra zurückgeschickt werden (ich war versucht, hier "an die Flüsse des Glaubens" zu schreiben :)).


1
Abgesehen davon, dass die JIT bei (kleinen) Schlüssellochoptimierungen wie dem Ersetzen eines booleschen Ausdrucks durch einen anderen sehr gut ist.
David Leppik

1
Außerdem ist ^ nicht primär ein boolescher (logischer) Operator, sondern ein bitweiser Operator. Es weist den Leser an, langsamer zu werden, da es wahrscheinlich Anzeichenfehler gibt. Wenn Sie ^ for! = Verwenden, werden Sie wirklich durcheinander geraten, wenn Sie jemals in C programmieren. Bitweise Operatoren sind ein Signal an Ihre Leser (diejenigen, die Ihren Code debuggen, einschließlich Sie), langsamer zu werden und nach Vorzeichenfehlern zu suchen . Und sie können schwierig sein. Wussten Sie zum Beispiel, dass Javas% kein echtes Modulo ist, wie in C oder Python? Ich hatte einmal einen Codeausschnitt, der in C, JavaScript und Python gleich lief, aber nicht in Java.
David Leppik

6
Wie wurde das jemals positiv bewertet? Erstens werden in Java XOR und! = Kompiliert [ stackoverflow.com/a/4175512/202504 weibl. (Auf genau denselben Code)), zweitens sind selbst bei Assembler-Tests auf Gleichheit und xor jeweils einzelne einfache Operationen. Haben Sie Zahlen, um Ihre Aussage zu stützen?
Jmiserez

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

sieht für mich besser aus als

str.contains("!=") != str.startsWith("not(")
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.