Creación de un operador "lógico exclusivo o" en Java

274

Observaciones:

Java tiene un operador lógico AND.
Java tiene un operador lógico OR.
Java tiene un operador lógico NOT.

Problema:

Java no tiene un operador XOR lógico, según sun . Me gustaría definir uno.

Definición del método:

Como método, simplemente se define de la siguiente manera:

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


Llamada de método:

Este método se llama de la siguiente manera:

boolean myVal = logicalXOR(x, y);


Uso del operador:

Preferiría tener un operador, que se utiliza de la siguiente manera:

boolean myVal = x ^^ y;


Pregunta:

No puedo encontrar nada sobre cómo definir un nuevo operador en Java. ¿Donde debería empezar?

once81
fuente
1
¿Qué? el enlace que proporcionó tiene el contenido 'OR exclusivo bit a bit'
Mathew P. Jones
¿se preguntaba si podría definir operadores en Java como puede hacerlo en C ++?
avgvstvs
1
Parece que entendiste mal la diferencia entre & y &&. Ambos son operadores lógicos (en un booleano). La respuesta de Starblue lo cubre más ampliamente.
Vlasec
el hecho de que no esté en el tutorial no significa que Java no lo tenga; los tutoriales no están (siempre) completos. Consulte la Especificación del lenguaje Java 15.22.2
user85421
55
Se llama !=, también hay un XNOR lógico llamado==
Mark K Cowan el

Respuestas:

695

Java tiene un operador XOR lógico , es ^ (como en a ^ b).

Aparte de eso, no puede definir nuevos operadores en Java.

Editar: Aquí hay un ejemplo:

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

Salida:

falso ^ falso = falso
falso ^ verdadero = verdadero
verdadero ^ falso = verdadero
verdadero ^ verdadero = falso
javashlook
fuente
55
Esto también escapó de mi memoria cuando escribí mi publicación, pero creo que PUEDES usar ^ como operador lógico (así como a nivel de bits).
Neil Coffey
144
^ no es solo un operador bit a bit. También es un operador lógico. El operador ^ está sobrecargado. Opera en tipos integrales o tipos booleanos. +1 para una gran respuesta javashlook. Eddie, no se vuelve más explícito que JLS Sección 15.22.2, "Operadores lógicos booleanos &, ^ y |".
erickson el
97
Y, por supuesto, la respuesta es que && y || omitirá la evaluación de la segunda parte de la expresión y & y | siempre evaluará ambas partes de la expresión (de mi lectura de JLS). A ^^ siempre tendría que evaluar ambas partes, por definición, por lo que se comporta de manera idéntica a ^. Probablemente por qué no hay ^^
Eddie
81
@Eddie: Eso y ^^ se parece demasiado a un emoticón.
Michael Myers
55
Tal vez sea una cuestión de semántica, pero cuando se trata de XOR, bit a bit y lógico producen el mismo resultado. Por lo tanto, no hay necesidad de operadores distintos. La tabla de verdad simplificada para un operador XOR es X ^! X = 1. No puede cortocircuitar una entrada en XOR porque debe determinar si las entradas son diferentes. Es mucho más fácil de entender si conoce la fabricación de la puerta XOR real.
hfontanez
305

¿No es x! = Y?

Maurice Perry
fuente
55
Si x e y son booleanos, entonces la tabla lógica para xor y! = Son idénticas: t, t => f; t, f => t; f, t => t; f, f => f
Greg Case
81
Maurice: Arrgh, acabas de volarme la cabeza! ¿Cómo nunca me di cuenta de esto?
8
@ Milhous ¿Estás diciendo a != b != cque no funcionará, pero lo a ^ b ^ chará? En ese caso, estás equivocado .
fredoverflow
3
Maurice, simplemente genial! Me sucede que pierdo cosas simples de la vista cuando hay mucho que hacer :)
sberezin
66
Este acercamiento implosiona cuando ambos lados son clases envolventes, new Boolean(true) != new Boolean(true)da true.
Vlastimil Ovčáčík
74

Java tiene un operador lógico AND.
Java tiene un operador lógico OR.

Incorrecto.

Java tiene

  • dos operadores lógicos AND: AND normal es & y cortocircuito AND es &&, y
  • dos operadores lógicos OR: OR normal es | y OR de cortocircuito es ||.

XOR existe solo como ^, porque la evaluación de cortocircuito no es posible.

starblue
fuente
2
Comentario interesante ¿Eso está documentado?
user666412
1
Pienso y | no son cortocircuitos porque son operadores bit a bit. Y, de hecho, no es posible cortocircuitarlos.
Krzysztof Jabłoński
3
@Krzysztof Jabłoński Son operadores bit a bit en números, pero aquí estamos hablando de expresiones booleanas.
Starblue
3
@ user666412 Sí, en la Especificación del lenguaje Java (¿dónde más?).
Starblue
18
Si tiene 2 operadores AND y 2 operadores OR, entonces las declaraciones 'Java tiene un operador AND lógico' y 'Java tiene un operador OR lógico' no están equivocadas. Por definición, si tienes 2 de algo, también tienes 1 de eso.
Ryanfae Escocia
31

Quizás haya entendido mal la diferencia entre &y &&, |y || El propósito de los operadores de acceso directo &&y ||es que el valor del primer operando puede determinar el resultado y, por lo tanto, no es necesario evaluar el segundo operando.

Esto es especialmente útil si el segundo operando resultaría en un error. p.ej

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

Sin embargo, con XOR , siempre debe evaluar el segundo operando para obtener el resultado, por lo que la única operación significativa es ^.

Peter Lawrey
fuente
20

Solo puedes escribir (a!=b)

Esto funcionaría de la misma manera que a ^ b.

Shuliyey
fuente
9

Esto se debe a que la sobrecarga del operador es algo que específicamente dejaron fuera del lenguaje deliberadamente. "Hicieron trampa" un poco con la concatenación de cadenas, pero más allá de eso, dicha funcionalidad no existe.

(descargo de responsabilidad: no he trabajado con los últimos 2 lanzamientos principales de java, así que si está ahora, me sorprenderé mucho)

Kevin Anderson
fuente
55
Tenga en cuenta que tampoco puede definir nuevos operadores en C ++. Todo lo que puedes hacer es dar nuevos significados a los viejos.
David Thornley el
7

La única sobrecarga de operadores en Java es + en cadenas ( JLS 15.18.1 Operador de concatenación de cadenas + ).

La comunidad se ha dividido en 3 durante años, 1/3 no lo quiere, 1/3 lo quiere y a 1/3 no le importa.

Puede usar unicode para crear nombres de métodos que sean símbolos ... así que si tiene un símbolo que desea usar, puede hacer myVal = x. $ (Y); donde $ es el símbolo yx no es una primitiva ... pero eso será dudoso en algunos editores y es limitante ya que no puede hacerlo en una primitiva.

TofuBeer
fuente
7

El siguiente su código:

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

Es superfluo.

Por qué no escribir:

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

?

Además, como dijo javashlook , ya hay un ^operador.

!=y ^funciona de forma idéntica * para operandos booleanos (su caso), pero de manera diferente para operandos enteros.

* Notas:
1. Funcionan de manera idéntica para operandos boolean(tipo primitivo), pero no Boolean(tipo de objeto). Como Boolean(tipo de objeto) los valores pueden tener valornull . Y !=regresará falseo truecuando uno o ambos de sus operandos lo estén null, mientras ^que NullPointerExceptionen este caso se lanzará .
2. Aunque funcionan de manera idéntica, tienen una precedencia diferente, por ejemplo, cuando se usan con &: a & b != c & dse tratarán como a & (b != c) & d, mientras a & b ^ c & dque se tratarán como (a & b) ^ (c & d)(fuera del tema: ouch, la tabla de precedencia de estilo C apesta).

Sasha
fuente
1
Para los valores booleanos que me gustan!=
GKalnytskyi
1
@GKalnytskyi para Booleanvalores !=funciona incorrectamente. Para los booleanvalores está bien.
vadipp
2
! = y ^ no funcionan de manera idéntica para operandos booleanos. Obtendrá diferentes resultados para "false & false! = True" versus "false & false ^ true" debido a la precedencia.
Albert Hendriks
1
@AlbertHendriks, mejor digo que funcionan de manera idéntica, pero tienen una prioridad diferente (aunque es solo una cuestión de terminología).
Sasha
6

Aquí hay un método var arg XOR para java ...

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

Disfrutar

Timothy Jacobsen
fuente
Parece que va a tener un comportamiento muy extraño. Por ejemplo, XOR(true,true,true)devuelve verdadero, que no parece lo que esperarías de un método llamado XOR. Mi comportamiento esperado sería que siempre devuelve falso (lo que, por supuesto, no es útil)
Richard Tingle
5

Se llama lógico exclusivo-o en Java !=. También puedes usarlo ^si quieres confundir a tus amigos.

Doradus
fuente
2

Puede usar Xtend (operadores de infix y sobrecarga de operadores) para sobrecargar a los operadores y 'quedarse' en Java

iga
fuente
Tenga en cuenta que Xtend no le permite anular el cursor ^; debes usar bool_1.xor(bool_2). Curiosamente, el analizador ni siquiera te permite usar el cursor; debes usar xorpara booleanos y bitwiseXorpara enteros. Podría, por supuesto, sobrecargar a otro operador, pero eso sería muy confuso.
Kelvin
2

Lo que estás pidiendo no tendría mucho sentido. A menos que sea incorrecto, está sugiriendo que desea usar XOR para realizar operaciones lógicas de la misma manera AND y OR. Su código provisto en realidad muestra a lo que me refiero:

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

Su función tiene entradas booleanas, y cuando se utiliza XOR bit a bit en booleanos, el resultado es el mismo que el código que ha proporcionado. En otras palabras, XOR bit a bit ya es eficiente al comparar bits individuales (booleanos) o al comparar los bits individuales en valores más grandes. Para poner esto en contexto, en términos de valores binarios, cualquier valor distinto de cero es VERDADERO y solo CERO es falso.

Entonces, para que XOR se aplique de la misma manera que se aplica AND lógico, solo usaría valores binarios con solo un bit (dando el mismo resultado y eficiencia) o el valor binario tendría que evaluarse como un todo en lugar de por bit. En otras palabras, la expresión (010 ^^ 110) = FALSO en lugar de (010 ^^ 110) = 100. Esto eliminaría la mayor parte del significado semántico de la operación, y representa una prueba lógica que no debería usar de todos modos.

user2904660
fuente
1

¡A y B tendrían que ser valores booleanos para hacer! = Lo mismo que xor para que la tabla de verdad se vea igual. También puedes usar! (A == B) lol.

John Theibert
fuente
1

Estoy usando la clase muy popular "org.apache.commons.lang.BooleanUtils"

Este método es probado por muchos usuarios y es seguro. Que te diviertas. Uso:

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

Dado que el tipo de datos booleanos se almacena como un entero, el operador de bit ^ funciona como una operación XOR si se usa con valores booleanos.

//©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
            */
        }
    }
Llevado en
fuente
0

Aquí hay un ejemplo:

Dados 2 valores int, devuelve verdadero si uno es negativo y el otro es positivo. Excepto si el parámetro "negativo" es verdadero, entonces devuelve verdadero solo si ambos son negativos.

    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
fuente