programacion operadores operador negacion logicos cortocircuito condicional asignacion c++ operators logical-operators

negacion - operadores logicos en c++



¿Operador lógico XOR en C++? (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 entradas, el resultado es siempre idéntico en las dos tablas.

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

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

La respuesta seria

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

O si quieres, escribe

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

¿Hay tal cosa? Es la primera vez que encuentro una necesidad práctica, pero no veo una 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 operador ^^ . ¿Puedo usar el bitwise ^ aquí y obtener la respuesta correcta (independientemente de la representación de máquina de verdadero y falso)? Nunca mezclo y & && , o | y || , así que vacilo en hacer eso con ^ y ^^ .

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


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


El operador XOR no puede ser cortocircuitado; es decir, no 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 ^^ .


Hay otra forma de hacer XOR:

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

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


La implementación lógica manual correcta de XOR depende de la medida en que desee 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 cuestión. Pero ¿qué pasa con 2? Si no te importa 2, entonces con el operador de valores normalizados (es decir, bool ) != Hace el trabajo de XOR en términos del resultado. ¡Y los operandos se pueden normalizar fácilmente con unario ! , si necesario. Por lo tanto !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 posible forma de hacer XOR (a, b) correctamente podría verse como sigue

a ? !b : b

Esto es en realidad lo más cerca que puede llegar a hacer un XOR hecho en casa "similar" a || y && . Por supuesto, esto solo funcionará si implementas tu XOR como una macro. Una función no funcionará, ya que la secuencia no se aplicará a los argumentos de la función.

Sin embargo, alguien podría decir que la única razón de tener una secuencia apunta a cada && y || es para apoyar la evaluación cortocircuitada y, por lo tanto, XOR no la necesita. Esto tiene sentido, en realidad. Sin embargo, 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

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

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

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


Para una verdadera operación XOR lógica, 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 la variable fuera 0 y 1 contrario. Podríamos haber usado !!A != !!B lugar. Otra forma de hacerlo es usar (_Bool)A != (_Bool)B


Se publicó un buen código que solucionó el problema mejor que! A! =! B

Tenga en cuenta que tuve que agregar 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


Utilice un simple:

return ((op1 ? 1 : 0) ^ (op2 ? 1 : 0));


Utilizo "xor" (parece que es una palabra clave; en Code::Blocks al menos se pone en negrita) tal como puede usar "y" en lugar de && y "o" en lugar de || .

if (first xor second)...

Sí, es bit a bit. Lo siento.


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

La primera parte es A OR 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 probado 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 | |-----|-----|-----------|


#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!)