Logische XOR-operator in C++?

Bestaat er zoiets? Het is de eerste keer dat ik er een praktische behoefte aan heb ondervonden, maar ik zie er geen vermeld in Stroustrup. Ik ben van plan te schrijven:

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

Maar er is geen ^^-operator. Kan ik de bitsgewijze ^ hier gebruiken en het juiste antwoord krijgen (ongeacht de machineweergave van waar en onwaar)? Ik mix nooit & en &&, of | en ||, dus ik aarzel om het te doen dat met ^ en ^^.

Ik zou liever mijn eigen bool XOR(bool,bool)-functie schrijven.


Antwoord 1, autoriteit 100%

De operator != dient dit doel voor !=-waarden.


Antwoord 2, autoriteit 45%

Voor een echte logische XOR-bewerking zal dit werken:

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

Let op de ! zijn er om de waarden om te zetten in booleans en ze te negeren, zodat twee ongelijke positieve gehele getallen (elk een true) zouden evalueren tot false.


Antwoord 3, autoriteit 7%

De juiste handmatige logische XOR-implementatie hangt af van hoe goed u het algemene gedrag van andere logische operatoren (|| en &&) met uw XOR. Er zijn twee belangrijke dingen aan deze operatoren: 1) ze garanderen kortsluitingsevaluatie, 2) ze introduceren een sequentiepunt, 3) ze evalueren hun operanden slechts één keer.

XOR-evaluatie kan, zoals u begrijpt, niet worden kortgesloten, aangezien het resultaat altijd van beide operanden afhangt. Dus 1 is uitgesloten. Maar hoe zit het met 2? Als je niet om 2 geeft, dan doet de operator != met genormaliseerde (d.w.z. !=) waarden het werk van XOR in termen van het resultaat. En de operanden kunnen indien nodig eenvoudig worden genormaliseerd met unaire !. Dus !A != !B implementeert in dat opzicht de juiste XOR.

Maar als je echter om het extra volgordepunt geeft, is noch != noch bitsgewijze ^ de juiste manier om XOR te implementeren. Een mogelijke manier om XOR(a, b) correct uit te voeren, zou er als volgt uit kunnen zien

a ? !b : b

Dit komt eigenlijk het dichtst in de buurt bij het maken van een zelfgemaakte XOR die “vergelijkbaar” is met || en &&. Dit werkt natuurlijk alleen als u uw XOR als macro implementeert. Een functie is niet voldoende, omdat de volgorde niet van toepassing is op de argumenten van de functie.

Iemand zou echter kunnen zeggen dat de enige reden voor het hebben van een volgordepunt bij elke && en || is om de kortgesloten evaluatie te ondersteunen, en dus XOR heeft er geen nodig. Dit is logisch, eigenlijk. Toch is het de moeite waard om te overwegen een XOR te hebben met een sequentiepunt in het midden. Bijvoorbeeld de volgende uitdrukking

++x > 1 && x < 5

heeft bepaald gedrag en specifiek resultaat in C/C++ (tenminste wat betreft sequencing). Je zou dus redelijkerwijs hetzelfde kunnen verwachten van door de gebruiker gedefinieerde logische XOR, zoals in

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

terwijl een op != gebaseerde XOR deze eigenschap niet heeft.


Antwoord 4, autoriteit 5%

Er is een andere manier om XOR te doen:

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

Wat uiteraard kan worden aangetoond om te werken via:

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

Antwoord 5, autoriteit 3%

De XOR-operator kan niet worden kortgesloten; d.w.z. u kunt het resultaat van een XOR-expressie niet voorspellen door alleen de linker operand te evalueren. Er is dus geen reden om een ​​^^-versie aan te bieden.


Antwoord 6, autoriteit 2%

Er is een goede code gepost die het probleem beter oploste dan !a != !b

Merk op dat ik de BOOL_DETAIL_OPEN/CLOSE moest toevoegen zodat het zou werken op 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

Antwoord 7

Gebruik een eenvoudige:

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

Antwoord 8

Zo denk ik dat je een XOR-vergelijking schrijft in 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
}

Bewijs

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

Het bewijs is dat een uitputtende studie van invoer en uitvoer aantoont dat in de twee tabellen voor elke invoerset het resultaat altijd identiek is in de twee tabellen.

Daarom is de oorspronkelijke vraag hoe te schrijven:

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

Het antwoord zou zijn

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

Of schrijf, als je wilt,

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

Antwoord 9

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

Het eerste deel is A OR B, wat de Inclusieve OR is; het tweede deel is, NIET A EN B. Samen krijg je A of B, maar niet zowel A als B.

Dit levert de XOR op die is bewezen in de onderstaande waarheidstabel.

|----- | ----- | -----------|
|  A  |  B  |  A XOR B  |
|----- | ----- | -----------|
|  T  |  T  |   False   |
|----- | ----- | -----------|
|  T  |  F  |   True    |
|----- | ----- | -----------|
|  F  |  T  |   True    |
|----- | ----- | -----------|
|  F  |  F  |   False   |
|----- | ----- | -----------|

Antwoord 10

Ik gebruik “xor” (het lijkt erop dat het een trefwoord is; in Code::Blocks het wordt in ieder geval vet) net zoals je “en” kunt gebruiken in plaats van && en “of” in plaats van ||.

if (first xor second)...

Ja, het is bitgewijs. Sorry.


Antwoord 11

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

Het werkt zoals gedefinieerd. De voorwaarden zijn om te detecteren of u Objective-C gebruikt, dat in plaats daarvan om BOOL vraagt van bool (de lengte is anders!)

LEAVE A REPLY

Please enter your comment!
Please enter your name here

three × five =

Other episodes