Tworzenie „logicznego wyłącznego lub” operatora w Javie

274

Obserwacje:

Java ma logiczny operator AND.
Java ma logiczny operator OR.
Java ma logiczny operator NOT.

Problem:

Według Sun Java nie ma logicznego operatora XOR . Chciałbym zdefiniować jeden.

Definicja metody:

Jako metodę definiuje się go następująco:

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


Wywołanie metody:

Ta metoda jest wywoływana w następujący sposób:

boolean myVal = logicalXOR(x, y);


Wykorzystanie operatora:

Wolałbym mieć operatora używanego w następujący sposób:

boolean myVal = x ^^ y;


Pytanie:

Nie mogę nic znaleźć na temat definiowania nowego operatora w Javie. Od czego powinienem zacząć

jedenaście81
źródło
1
co? podany link ma treść „bitwise exclusive OR”
Mathew P. Jones
zastanawiałeś się wtedy, czy możesz zdefiniować operatorów w Javie tak jak w C ++?
avgvstvs
1
Wygląda na to, że źle zrozumiałeś różnicę między & i &&. Oba są operatorami logicznymi (na boolean). Odpowiedź Starblue obejmuje ją szerzej.
Vlasec
tylko dlatego, że nie ma go w samouczku , nie oznacza, że ​​Java go nie ma - samouczki nie są (zawsze) kompletne. Zobacz specyfikację języka Java 15.22.2
użytkownik85421,
5
To się nazywa !=, istnieje też logiczny XNOR o nazwie==
Mark K Cowan

Odpowiedzi:

695

Java ma logiczny operator XOR , jest ^ (jak w a ^ b).

Poza tym nie można definiować nowych operatorów w Javie.

Edycja: Oto przykład:

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);
        }
    }
}

Wynik:

false ^ false = false
false ^ true = true
true ^ false = true
true ^ true = false
javashlook
źródło
5
To również uciekło mi z pamięci, kiedy napisałem mój post, ale myślę, że MOŻESZ użyć ^ jako operatora logicznego (jak również bitowego).
Neil Coffey,
144
^ jest nie tylko operatorem bitowym. Jest także operatorem logicznym. Operator ^ jest przeciążony. Działa na typach integralnych lub typach boolowskich. +1 za świetną odpowiedź javashlook. Eddie, nie robi się bardziej wyraźny niż sekcja 15.22.2 JLS, „Boolean Logical Operators &, ^ i |”.
erickson,
97
Oczywiście odpowiedź brzmi: && i || pominie ocenę 2. części wyrażenia oraz & i | zawsze oceni obie części wyrażenia (z mojej lektury JLS). ^^ zawsze musiałby oceniać obie części z definicji, więc zachowuje się identycznie jak ^. Prawdopodobnie dlaczego nie ma ^^
Eddie
81
@Eddie: To i ^^ po prostu wygląda za bardzo jak emotikon.
Michael Myers
5
Być może jest to kwestia semantyki, ale jeśli chodzi o XOR, bitowe i logiczne dają ten sam wynik. Dlatego nie ma potrzeby stosowania odrębnych operatorów. Uproszczona tabela prawdy dla operatora XOR to X ^! X = 1. Nie można zwierać wejścia w XOR, ponieważ trzeba ustalić, czy wejścia są różne. O wiele łatwiej jest zrozumieć, jeśli znasz konstrukcję faktycznej bramki XOR.
hfontanez
305

Czy to nie x! = Y?

Maurice Perry
źródło
5
Jeśli xiy są wartościami logicznymi, to tablica logiczna dla xor i! = Są identyczne: t, t => f; t, f => t; f, t => t; f, f => f
Greg Case
81
Maurice: Arrgh, po prostu oszalałeś! Jak tego nigdy nie zauważyłem?
8
@Milhous Mówisz, że a != b != cnie będzie działać, ale a ^ b ^ cbędzie? W takim razie się mylisz .
fredoverflow
3
Maurice, po prostu genialny! Zdarza mi się tracić z oczu proste rzeczy, gdy jest wiele do zrobienia :)
sberezin
6
To podejście imploduje, gdy obie strony są klasami otoki, new Boolean(true) != new Boolean(true)daje true.
Vlastimil Ovčáčík
74

Java ma logiczny operator AND.
Java ma logiczny operator OR.

Źle.

Java ma

  • dwa logiczne operatory AND: normalny AND to & oraz zwarcie AND jest && i
  • dwa logiczne operatory OR: normalne OR to | a zwarcie OR wynosi ||.

XOR istnieje tylko jako ^, ponieważ ocena zwarcia nie jest możliwa.

starblue
źródło
2
Ciekawy komentarz. Czy to jest udokumentowane?
user666412
1
Myślę, że i | nie powodują zwarcia, ponieważ są operatorami bitowymi. W rzeczywistości nie można ich zwierać.
Krzysztof Jabłoński
3
@Krzysztof Jabłoński Są to operatory bitowe na liczbach, ale tutaj mówimy o wyrażeniach boolowskich.
starblue
3
@ user666412 Tak, w specyfikacji języka Java (gdzie indziej?).
starblue
18
Jeśli ma 2 operatory AND i 2 operatory OR, wówczas instrukcje „Java ma logicznego operatora AND” i „Java ma logicznego operatora OR” nie są błędne. Z definicji, jeśli masz 2 coś, to również masz 1.
RyanfaeScotland
31

Być może zrozumiał różnicę między &i &&, |a || Zadaniem operatorów skrótów &&i ||jest to, że wartość pierwszego argumentu można określić rezultat, a więc drugi argument nie musi być ocenione.

Jest to szczególnie przydatne, jeśli drugi operand spowoduje błąd. na przykład

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

Jednak w przypadku XOR zawsze musisz ocenić drugi operand, aby uzyskać wynik, więc jedyną znaczącą operacją jest ^.

Peter Lawrey
źródło
20

Możesz po prostu pisać (a!=b)

To działałoby tak samo jak a ^ b.

Shuliyey
źródło
9

To dlatego, że przeciążanie operatorów jest czymś, co specjalnie pominęli z języka. „Oszukiwali” trochę poprzez łączenie łańcuchów, ale poza tym taka funkcjonalność nie istnieje.

(zrzeczenie się: Nie pracowałem z 2 ostatnimi ważnymi wydaniami Javy, więc jeśli będzie to teraz, będę bardzo zaskoczony)

Kevin Anderson
źródło
5
Pamiętaj, że nie możesz również definiować nowych operatorów w C ++. Wszystko, co możesz zrobić, to nadać starym znaczenie nowym znaczeniom.
David Thornley,
7

Jedynym przeciążeniem operatora w Javie jest + na ciągach ( JLS 15.18.1 Operator konkatenacji ciągów + ).

Społeczność jest podzielona na 3 lata, 1/3 tego nie chce, 1/3 chce, a 1/3 nie obchodzi.

Możesz użyć Unicode do tworzenia nazw metod, które są symbolami ... więc jeśli masz symbol, którego chcesz użyć, możesz zrobić myVal = x. $ (Y); gdzie $ jest symbolem, a x nie jest prymitywne ... ale będzie to podejrzane w niektórych edytorach i jest ograniczone, ponieważ nie można tego zrobić na prymitywie.

TofuBeer
źródło
7

Twój kod:

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

jest zbyteczny.

Dlaczego nie napisać:

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

?

Ponadto, jak powiedział javashlook , istnieje już ^operator.

!=i ^działają identycznie * dla operandów boolowskich (twój przypadek), ale inaczej dla operandów całkowitych.

* Uwagi:
1. Działają identycznie dla operandów boolean(typ pierwotny), ale nie działają Boolean(typ obiektu). Ponieważ Boolean(typ obiektu) wartości mogą mieć wartość null. I !=powróci falselub truegdy jeden lub oba operandy będą null, podczas gdy w tym przypadku ^rzuci NullPointerException.
2. Chociaż działają identycznie, mają różne pierwszeństwo, np. Gdy są używane z &: a & b != c & dbędą traktowane jako a & (b != c) & d, podczas gdy a & b ^ c & dbędą traktowane jako (a & b) ^ (c & d)(offtopic: ouch, tabela pierwszeństwa w stylu C jest do bani).

Sasha
źródło
1
Dla wartości logicznych lubię!=
GKalnytskyi
1
@GKalnytskyi dla Booleanwartości !=działa niepoprawnie. W przypadku booleanwartości jest w porządku.
vadipp
2
! = i ^ nie działają identycznie dla operandów boolowskich. Otrzymasz różne wyniki dla „fałsz i fałsz! = Prawda” kontra „fałsz i fałsz ^ prawda” ze względu na pierwszeństwo.
Albert Hendriks,
1
@AlbertHendriks, lepiej powiedzieć, że działają identycznie, ale mają inny priorytet (choć to tylko kwestia terminologii).
Sasha
6

Oto metoda var arg XOR dla java ...

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

Cieszyć się

Timothy Jacobsen
źródło
To wydaje się mieć dziwne zachowanie. Np. XOR(true,true,true)Zwraca true, co nie wydaje się być tym, czego można oczekiwać od metody o nazwie XOR. Moim oczekiwanym zachowaniem byłoby to, że zawsze zwraca false (co oczywiście nie jest pomocne)
Richard Tingle,
4

Nazywa się to logiczne wyłączne lub w Javie !=. Możesz także użyć, ^jeśli chcesz zmylić znajomych.

Doradus
źródło
2

Możesz użyć Xtend (Infix Operators and Operator Overloading) do przeciążenia operatorów i „pozostania” na Javie

iga
źródło
Zauważ, że Xtend nie pozwala ci przesłonić karetki ^; musisz użyć bool_1.xor(bool_2). Co dziwne, analizator składni nie pozwala nawet na użycie kursora; musisz użyć xordla wartości logicznych i bitwiseXorliczb całkowitych. Oczywiście możesz przeciążyć innego operatora, ale byłoby to bardzo mylące.
Kelvin,
2

To, o co prosisz, nie miałoby większego sensu. O ile się nie mylę, sugerujesz, że chcesz używać XOR do wykonywania operacji logicznych w taki sam sposób, jak AND i OR. Podany kod pokazuje, o co mi chodzi:

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

Twoja funkcja ma dane logiczne, a gdy bitowa XOR jest używana na boolach, wynik jest taki sam, jak podany kod. Innymi słowy, bitowe XOR jest już wydajne podczas porównywania pojedynczych bitów (booleanów) lub porównywania pojedynczych bitów w większych wartościach. Aby umieścić to w kontekście, pod względem wartości binarnych każda niezerowa wartość ma wartość PRAWDA, a tylko ZERO jest fałszem.

Tak więc, aby XOR mógł być zastosowany w taki sam sposób, jak logiczny AND, albo użyłbyś tylko wartości binarnych z jednym bitem (dając ten sam wynik i wydajność), albo wartość binarna musiałaby być oceniana jako całość zamiast na bit. Innymi słowy, wyrażenie (010 ^^ 110) = FAŁSZ zamiast (010 ^^ 110) = 100. To usunie większość znaczenia semantycznego z operacji i reprezentuje logiczny test, którego i tak nie powinieneś używać.

użytkownik2904660
źródło
1

A i B musiałyby być wartościami logicznymi, aby! = Taki sam jak xor, aby tablica prawdy wyglądała tak samo. Możesz także użyć! (A == B) lol.

John Theibert
źródło
1

Korzystam z bardzo popularnej klasy „org.apache.commons.lang.BooleanUtils”

Ta metoda jest testowana przez wielu użytkowników i bezpieczna. Baw się dobrze. Stosowanie:

boolean result =BooleanUtils.xor(new boolean[]{true,false});
Adam111p
źródło
0

Ponieważ typ danych logicznych jest przechowywany jak liczba całkowita, operator bitowy ^ działa jak operacja XOR, jeśli jest używany z wartościami logicznymi.

//©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
            */
        }
    }
Ledón
źródło
0

Oto przykład:

Biorąc pod uwagę 2 wartości int, zwróć true, jeśli jedna jest ujemna, a druga dodatnia. Z wyjątkiem sytuacji, gdy parametr „przeczący” jest prawdziwy, zwróć wartość prawdy tylko wtedy, gdy oba są ujemne.

    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);
    }
Shadman Sudipto
źródło