¿Operador lógico XOR en C++?


¿existe tal cosa? Es la primera vez que encuentro una necesidad práctica para ello, pero no veo una lista en Stroustrup. Tengo la intención de escribir:

// Detect when exactly one of A,B is equal to five.
return (A==5) ^^ (B==5);

Pero no hay un operador ^^. ¿Puedo usar el bitwise ^ aquí y obtener la respuesta correcta (independientemente de la representación de la máquina de verdadero y falso)? Nunca mezclo & y &&, o | y ||, así que dudo en hacer eso con ^ y ^^.

Estaría más cómodo escribiendo mi propia función bool XOR(bool,bool) en su lugar.

Author: jotik, 2009-10-20

11 answers

El operador != sirve para este propósito para los valores bool.

 451
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-20 19:03:38

Para una verdadera operación lógica XOR, esto funcionará:

if(!A != !B) {
    // code here
}

La razón por la que negamos A y B es para convertirlos a booleanos. La negación no es la intención. Un truco común para convertir enteros a booleanos es usar !!. Esto convertirá el valor de una variable a 0 si la variable era 0 y 1 de lo contrario. Podríamos haber usado !!A != !!B en su lugar. Otra forma de hacerlo es usar (_Bool)A != (_Bool)B.

 201
Author: LiraNuna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-10 00:38:13

Manual apropiado lógico La implementación de XOR depende de qué tan cerca se desea imitar el comportamiento general de otros operadores lógicos (|| y &&) con su XOR. Hay dos cosas importantes acerca de estos operadores: 1) garantizan la evaluación de cortocircuito, 2) introducen un punto de secuencia, 3) evalúan sus operandos solo una vez.

La evaluación XOR, como usted entiende, no puede ser cortocircuitada ya que el resultado siempre depende de ambos operandos. Así que 1 está fuera de pregunta. ¿Pero qué pasa con 2? Si no le importa 2, entonces con valores normalizados (es decir, bool) el operador != hace el trabajo de XOR en términos del resultado. Y los operandos pueden ser fácilmente normalizados con unary !, si es necesario. Así !A != !B implementa el XOR apropiado en ese sentido.

Pero si te importa el punto de secuencia adicional, sin embargo, ni != ni bitwise ^ es la forma correcta de implementar XOR. Una forma posible de hacer XOR (a, b) correctamente podría verse como sigue

a ? !b : b

Esto es en realidad lo más cercano que puedes llegar a hacer un XOR casero "similar" a || y &&. Esto solo funcionará, por supuesto, si implementa su XOR como una macro. Una función no funcionará, ya que la secuenciación no se aplicará a los argumentos de la función.

Alguien podría decir, sin embargo, que la única razón de tener un punto de secuencia en cada && y || es para apoyar la evaluación en cortocircuito, y por lo tanto XOR no necesita uno. Esto tiene sentido, en realidad. Aun, vale la pena considerar tener un XOR con un punto de secuencia en el medio. Por ejemplo, la siguiente expresión

++x > 1 && x < 5

Tiene un comportamiento definido y un resultado específico en C/C++ (con respecto a la secuenciación al menos). Por lo tanto, uno podría esperar razonablemente lo mismo de lógico XOR definido por el usuario, como en

XOR(++x > 1, x < 5)

Mientras que un XOR basado en != no tiene esta propiedad.

 35
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-18 17:35:12

Hay otra manera de hacer XOR:

bool XOR(bool a, bool b)
{
    return (a + b) % 2;
}

Que obviamente se puede demostrar que funciona a través de:

#include <iostream>

bool XOR(bool a, bool b)
{
    return (a + b) % 2;
}

int main()
{
    using namespace std;
    cout << "XOR(true, true):\t" << XOR(true, true) << endl
         << "XOR(true, false):\t" << XOR(true, false) << endl
         << "XOR(false, true):\t" << XOR(false, true) << endl
         << "XOR(false, false):\t" << XOR(false, false) << endl
         << "XOR(0, 0):\t\t" << XOR(0, 0) << endl
         << "XOR(1, 0):\t\t" << XOR(1, 0) << endl
         << "XOR(5, 0):\t\t" << XOR(5, 0) << endl
         << "XOR(20, 0):\t\t" << XOR(20, 0) << endl
         << "XOR(6, 6):\t\t" << XOR(5, 5) << endl
         << "XOR(5, 6):\t\t" << XOR(5, 6) << endl
         << "XOR(1, 1):\t\t" << XOR(1, 1) << endl;
    return 0;
}
 25
Author: Bertie Wheen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-12 15:08:54

El operador XOR no puede ser cortocircuitado; es decir, no se puede predecir el resultado de una expresión XOR simplemente evaluando su operando de la mano izquierda. Por lo tanto, no hay razón para proporcionar una versión ^^.

 16
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-20 19:02:53

Hubo un buen código publicado que resolvió el problema mejor que !¡a != !b

Tenga en cuenta que tuve que agregar el BOOL_DETAIL_OPEN / CLOSE para que funcionara en MSVC 2010

/* From: http://groups.google.com/group/comp.std.c++/msg/2ff60fa87e8b6aeb

   Proposed code    left-to-right?  sequence point?  bool args?  bool result?  ICE result?  Singular 'b'?
   --------------   --------------  ---------------  ---------- ------------  -----------  -------------
   a ^ b                  no              no             no          no           yes          yes
   a != b                 no              no             no          no           yes          yes
   (!a)!=(!b)             no              no             no          no           yes          yes
   my_xor_func(a,b)       no              no             yes         yes          no           yes
   a ? !b : b             yes             yes            no          no           yes          no
   a ? !b : !!b           yes             yes            no          no           yes          no
   [* see below]          yes             yes            yes         yes          yes          no
   (( a bool_xor b ))     yes             yes            yes         yes          yes          yes

   [* = a ? !static_cast<bool>(b) : static_cast<bool>(b)]

   But what is this funny "(( a bool_xor b ))"? Well, you can create some
   macros that allow you such a strange syntax. Note that the
   double-brackets are part of the syntax and cannot be removed! The set of
   three macros (plus two internal helper macros) also provides bool_and
   and bool_or. That given, what is it good for? We have && and || already,
   why do we need such a stupid syntax? Well, && and || can't guarantee
   that the arguments are converted to bool and that you get a bool result.
     Think "operator overloads". Here's how the macros look like:

   Note: BOOL_DETAIL_OPEN/CLOSE added to make it work on MSVC 2010
  */

#define BOOL_DETAIL_AND_HELPER(x) static_cast<bool>(x):false
#define BOOL_DETAIL_XOR_HELPER(x) !static_cast<bool>(x):static_cast<bool>(x)

#define BOOL_DETAIL_OPEN (
#define BOOL_DETAIL_CLOSE )

#define bool_and BOOL_DETAIL_CLOSE ? BOOL_DETAIL_AND_HELPER BOOL_DETAIL_OPEN
#define bool_or BOOL_DETAIL_CLOSE ? true:static_cast<bool> BOOL_DETAIL_OPEN
#define bool_xor BOOL_DETAIL_CLOSE ? BOOL_DETAIL_XOR_HELPER BOOL_DETAIL_OPEN
 10
Author: elegant dice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-06 03:06:02

Utilice un simple:

return ((op1 ? 1 : 0) ^ (op2 ? 1 : 0));
 5
Author: tiands,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-18 20:55:11

Así es como creo que escribes una comparación XOR en C++:

bool a = true;   // Test by changing to true or false
bool b = false;  // Test by changing to true or false
if (a == !b)     // THIS IS YOUR XOR comparison
{
    // do whatever
}

Prueba

XOR TABLE
 a   b  XOR
--- --- ---
 T   T   F
 T   F   T
 F   T   T
 F   F   F

a == !b TABLE
 a   b  !b  a == !b
--- --- --- -------
 T   T   F     F
 T   F   T     T
 F   T   F     T
 F   F   T     F

La prueba es que un estudio exhaustivo de entradas y salidas muestra que en las dos tablas, para cada conjunto de entrada el resultado es siempre el mismo en las dos tablas.

Por lo tanto, la pregunta original es cómo escribir:

return (A==5) ^^ (B==5)

, La respuesta sería

return (A==5) == !(B==5);

O si quieres, escribe

return !(A==5) == (B==5);
 4
Author: Indinfer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-13 15:00:50

(A || B) && !(A && B)

La primera parte es A O B, que es el OR Inclusivo; la segunda parte ES, NO A Y B. Juntos obtienes A o B, pero no ambos A y B.

Esto proporcionará el XOR demostrado en la tabla de verdad a continuación.

|-----|-----|-----------|
|  A  |  B  |  A XOR B  |
|-----|-----|-----------|
|  T  |  T  |   False   |
|-----|-----|-----------|
|  T  |  F  |   True    |
|-----|-----|-----------|
|  F  |  T  |   True    |
|-----|-----|-----------|
|  F  |  F  |   False   |
|-----|-----|-----------|
 3
Author: Eat at Joes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-28 00:58:20

Uso "xor" (parece que es una palabra clave; en Code::Blocks al menos se pone en negrita) así como puedes usar "and" en lugar de && y "or" en lugar de ||.

if (first xor second)...

Sí, es bit a bit. Disculpe....

 1
Author: csiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-18 20:52:30
#if defined(__OBJC__)
    #define __bool BOOL
    #include <stdbool.h>
    #define __bool bool
#endif

static inline __bool xor(__bool a, __bool b)
{
    return (!a && b) || (a && !b);
}

Funciona como se define. Los condicionales son para detectar si está utilizando Objective-C, que está pidiendo BOOL en lugar de bool (la longitud es diferente!)

 -1
Author: Maxthon Chan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-12 15:09:54