C ++ में तार्किक XOR ऑपरेटर?


292

क्या वहां ऐसी कोई चीज है? यह पहली बार है जब मुझे इसके लिए एक व्यावहारिक आवश्यकता का सामना करना पड़ा, लेकिन मैं स्ट्रॉस्ट्रुप में सूचीबद्ध किसी को नहीं देखता । मेरा लिखने का इरादा है:

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

लेकिन कोई ^^ऑपरेटर नहीं है। क्या मैं ^यहां बिटवाइज़ का उपयोग कर सकता हूं और सही उत्तर प्राप्त कर सकता हूं (सच और झूठ की मशीन प्रतिनिधित्व की परवाह किए बिना)? मैं कभी आपस में ना &और &&, या |और ||, इसलिए मुझे लगता है कि ऐसा करने के लिए साथ में संकोच ^और ^^

मैं bool XOR(bool,bool)इसके बजाय अपने स्वयं के फ़ंक्शन लिखना अधिक आरामदायक होगा।


57
वास्तव में, जिम, उदाहरण के लिए & && के बीच केवल यही अंतर नहीं है ... 1 && 2 सत्य है। लेकिन 1 & 2 => 0. इस वजह से, मुझे लगता है कि "शॉर्ट सर्किटिंग" सिर्फ एक संपत्ति है जो उनके पास होती है। लॉजिकल है ज्यादा जरूरी फीचर ...
ब्रायन पोस्टो

6
उल्लेख नहीं है कि 2 && 3 == सही है, लेकिन 2 और 3 == 2.
डेविड थॉर्नले

1
डेविड थॉम्ले: ठीक है, हाँ, लेकिन 2 ==> सच है, तो यह ठीक है ... याद रखें, वास्तव में कोई
बूलियन

13
@BrianPostow: वास्तव में, C ++ में, हैं।
एड्रियन विलेनबचेर

7
नीचे पोस्ट के रूप में, यहाँ डेनिस रिची का उत्तर क्यों मौजूद नहीं है: c-faq.com/misc/xorinosr.html
टोबिया

जवाबों:


536

!=ऑपरेटर के लिए इस उद्देश्य में कार्य करता boolमूल्यों।


7
लेकिन झूठा! = झूठा => झूठा
जोनास

13
ध्यान दें कि यह केवल बूलियन के लिए काम करता है। और ^ पूरी तरह से वहाँ अच्छी तरह से काम करेगा। 2! = 1 => 1 जो आप नहीं चाहते हैं! LiraNuna कहते हैं, एक डाल! दोनों पक्षों के उल्लंघन से उस समस्या का समाधान होता है। लेकिन फिर, तब आप
बिटवाइन का

8
ठीक है, मैं " boolमूल्यों के लिए" का उल्लेख करने के लिए सावधान था क्योंकि यह जरूरी नहीं कि आप गैर-बूलियन के लिए क्या कर सकते हैं। और जैसा कि यह C ++ है, उस उद्देश्य के boolलिए उपयोग करने के बजाय एक वास्तविक प्रकार मौजूद है int
ग्रेग हेविगेल

29
यदि आप इसे aलिखना चाहते हैं तो लिखें!(a) != !(a)
क्रिस लुत्ज़

6
@ क्रिसलुट्ज़: हाँ, लेकिन अतिभारित ऑपरेटरों से सावधान रहें।
रोंगोंग

246

एक सच्चे तार्किक XOR ऑपरेशन के लिए, यह काम करेगा:

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

ध्यान दें कि !मूल्यों को बूलियंस में परिवर्तित करने और उन्हें नकारात्मक करने के लिए है, ताकि दो असमान सकारात्मक पूर्णांक (प्रत्येक true) का मूल्यांकन हो सके false


6
मुझे समझ नहीं आ रहा है कि A और B किस कारण से उपेक्षित हैं!
मार्टिन हैनसेन

26
मुख्य रूप से उन्हें बूलियन में बदलने के लिए। !!काम सिर्फ अच्छी तरह से पूछेंगे, लेकिन चूंकि उन्हें अलग होने की जरूरत है, इसलिए उन्हें नकारने से कोई नुकसान नहीं है।
लीराउना

4
प्रश्न यह है कि क्या कंपाइलर इसे ठीक से ऑप्टिमाइज़ करने में सक्षम हैं।
ईनपोकलम

6
सामान्यीकरण के महत्व को न जानने के कारण मुझे 2 दिन लग गए।
माकन तैयबी

9
@ लीरुना, "ए और बी के साथ नकारात्मकता क्यों है!" / "मुख्य रूप से उन्हें बूलियन में बदलने के लिए।" - मुझे लगता है कि यह जवाब में ध्यान देने योग्य है।
cp.engr

42

उचित मैनुअल तार्किक XOR कार्यान्वयन इस बात पर निर्भर करता है कि आप अपने XOR के साथ अन्य तार्किक ऑपरेटरों ( ||और &&) के सामान्य व्यवहार की कितनी बारीकी से नकल करना चाहते हैं । इन ऑपरेटरों के बारे में दो महत्वपूर्ण बातें हैं: 1) वे शॉर्ट-सर्किट मूल्यांकन की गारंटी देते हैं, 2) वे एक अनुक्रम बिंदु पेश करते हैं, 3) वे केवल एक बार अपने ऑपरेंड का मूल्यांकन करते हैं।

XOR मूल्यांकन, जैसा कि आप समझते हैं, शॉर्ट-सर्कुलेट नहीं किया जा सकता क्योंकि परिणाम हमेशा दोनों ऑपरेंड पर निर्भर करता है। तो 1 प्रश्न से बाहर है। लेकिन 2 के बारे में क्या? यदि आप 2 के बारे में परवाह नहीं करते हैं, तो परिणाम के संदर्भ में सामान्यीकृत (यानी bool) मान ऑपरेटर !=XOR का काम करता है। और !यदि आवश्यक हो, तो संचालन को आसानी से एकरी से सामान्य किया जा सकता है। इस प्रकार !A != !Bउस संबंध में उचित XOR को लागू करता है।

लेकिन अगर आप अतिरिक्त अनुक्रम बिंदु के बारे में परवाह करते हैं, तो !=न तो और न ही बिटकॉइन ^XOR को लागू करने का उचित तरीका है। एक्सओआर (ए, बी) करने का एक संभावित तरीका सही रूप में निम्नानुसार लग सकता है

a ? !b : b

यह वास्तव में उतना ही करीब है जितना कि आप एक होममेड XOR को " ||और " के समान बना सकते हैं &&। यह केवल तभी काम करेगा, जब आप अपने XOR को मैक्रो के रूप में लागू करेंगे। एक फ़ंक्शन नहीं करेगा, क्योंकि अनुक्रमण फ़ंक्शन के तर्कों पर लागू नहीं होगा।

हालांकि, कोई कह सकता है कि प्रत्येक पर अनुक्रम बिंदु होने का एकमात्र कारण &&और ||शॉर्ट-सर्कुलेटेड मूल्यांकन का समर्थन करना है, और इस प्रकार XOR को एक की आवश्यकता नहीं है। यह वास्तव में समझ में आता है। फिर भी, यह बीच में एक अनुक्रम बिंदु के साथ XOR होने पर विचार करने के लायक है। उदाहरण के लिए, निम्नलिखित अभिव्यक्ति

++x > 1 && x < 5

सी / सी ++ में व्यवहार और विशिष्ट परिणाम को परिभाषित किया है (कम से कम अनुक्रमण के संबंध में)। इसलिए, उपयोगकर्ता यथोचित तार्किक XOR से समान रूप से उम्मीद कर सकता है

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

जबकि !=एक्स-आधारित एक्सओआर के पास यह संपत्ति नहीं है।


1
आप के बारे में अन्य महत्वपूर्ण बात याद आ रही है : ||और &&(ग) वे एक बूलियन संदर्भ में ऑपरेंड का मूल्यांकन करते हैं। अर्थात्, 1 && 2सत्य है, 1 & 2जिसके विपरीत शून्य है। इसी तरह, एक ^^ऑपरेटर इस अतिरिक्त सुविधा प्रदान करने के लिए उपयोगी हो सकता है, औपनिवेशिक संदर्भ में ऑपरेटरों के मूल्यांकन के लिए। उदाहरण 1 ^^ 2गलत है (विपरीत 1 ^ 2)।
क्रेग मैकक्वीन

2
@ क्रेग मैकक्वीन: मैं इसे याद नहीं कर रहा हूं। मेरी पोस्ट के दूसरे पैराग्राफ में इसका उल्लेख है। मेरी राय में, बूलियन मूल्यों के रूप में ऑपरेंड्स का इलाज करना तार्किक ऑपरेटरों की एक महत्वपूर्ण विशेषता नहीं है, इस अर्थ में कि उन्हें केवल उसी कारण से पेश नहीं किया जाएगा। उन्हें पेश किए जाने का मुख्य कारण कम परिचालित मूल्यांकन और उसके लिए आवश्यक अनुक्रम बिंदु है।
चींटी

आजकल, क्या आपका सुझाव अभी भी केवल एक मैक्रो के साथ काम करेगा? हालांकि यह सही है कि किसी फ़ंक्शन में मूल्यांकन किए जाने वाले मापदंडों का क्रम संकलक-निर्भर है, क्या यह वर्तमान में बाएं से दाएं से अलग होने के लिए दुर्लभ है? इसके अलावा, यहां टिप्पणियों में यह ध्यान देने योग्य हो सकता है कि यदि कोई कार्यान्वयन जैसा दिखता है #define XOR(ll,rr) { ll ? !rr : rr }, तो कॉल जैसी कॉल int x = 2; XOR(++x > 1, x < 5);गलत परिणाम देगी। int x = 2; XOR( (++x > 1), (x < 5) );सही अपेक्षित परिणाम देने के लिए कॉल में अतिरिक्त कोष्ठक होने चाहिए।
रास

1
चूंकि XOR शॉर्ट-सर्किट नहीं कर सकता, इसलिए अनुक्रम-बिंदु की कोई आवश्यकता नहीं है। उस संबंध में XOR अधिक + पसंद है। जब तक आप भी (++ x) + x को 2x + 1 के बराबर होने के लिए तर्क देना चाहते हैं, अनुक्रम बिंदु उचित नहीं है।
hkBst

1
@hkBst: मुझे लगता है कि यह मेरे उत्तर के दूसरे भाग में पूरी तरह से शामिल है।
चींटी

25

XOR करने का एक और तरीका है:

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

जो स्पष्ट रूप से के माध्यम से काम करने के लिए प्रदर्शित किया जा सकता है:

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

7
यह दृष्टिकोण कुछ काफी धीमा कोड उत्पन्न कर सकता है - (a) की तुलना में (a)! =! (! B) दोनों क्लैब
xaxxon

18

XOR ऑपरेटर कम परिचालित नहीं किया जा सकता है; यानी आप केवल XOR अभिव्यक्ति के परिणाम का अनुमान नहीं लगा सकते हैं कि इसके बाएं हाथ के ऑपरेंड का मूल्यांकन कर सकते हैं। इस प्रकार, एक ^^संस्करण प्रदान करने का कोई कारण नहीं है ।


25
-1 और & के बीच मुख्य अंतर सिर्फ शॉर्ट सर्किटिंग का नहीं है। 1 && 2 सत्य है, लेकिन 1 और 2 असत्य है। शॉर्ट सर्किटिंग सिर्फ एक आसान साइड इफेक्ट है।
ब्रायन पोस्टो

6
जवाब के बारे में बात नहीं कर रहा है &&और &सब पर। इसकी बात यह है कि परिचय का कोई कारण नहीं है ^^। संपत्ति जो ^^किसी भी गैर-शून्य मान के रूप 1में वास्तव में उपयोगी नहीं है, मुझे संदेह है। या कम से कम मैं कोई उपयोग नहीं देख सकता।
जोहान्स स्काउब -

6
इसके अलावा C ++! = अन्य-भाषाएँ। C और C ++ में जैसा कि शॉर्ट सर्किट के ऊपर दिखाया गया है, यह न केवल कुछ-अच्छा-से-सामान है बल्कि यह मौलिक रूप से महत्वपूर्ण है। :)
जोहान्स स्काउब -

13
तब आपको डेनिस रिची के जवाब को पढ़ना चाहिए कि यह क्यों मौजूद नहीं है: it.usyd.edu.au/~dasymond/mirror/c-faq/misc/xorinosr.html
जोहान्स

5
यहां डेनिस रिची के जवाब पर एक काम कर रहा है कि यह क्यों मौजूद नहीं है: c-faq.com/misc/xorinosr.html
टोबिया

13

वहाँ कुछ अच्छा कोड पोस्ट किया गया था जो समस्या को हल करने से बेहतर था! (! B!

ध्यान दें कि मुझे BOOL_DETAIL_OPEN / CLOSE जोड़ना था इसलिए यह 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

6

एक सरल प्रयोग करें:

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

5

यहाँ मुझे लगता है कि आप C ++ में XOR तुलना कैसे लिखते हैं:

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
}

सबूत

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

प्रमाण यह है कि इनपुट और आउटपुट के एक संपूर्ण अध्ययन से पता चलता है कि दो तालिकाओं में, प्रत्येक इनपुट सेट के लिए परिणाम दो तालिकाओं में हमेशा समान होता है।

इसलिए, मूल प्रश्न यह है कि कैसे लिखें:

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

जवाब होगा

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

या पसंद आए तो लिखें

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

a! =! b अच्छा लग रहा है क्योंकि यह आपके तर्क को आपके लिए बूल में बदल देता है।
xaxxon

3

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

पहला भाग A OR B है, जो समावेशी OR है; दूसरा भाग है, A और B नहीं, साथ में आपको A या B मिलता है, लेकिन A और B दोनों नहीं।

यह नीचे दिए गए सत्य तालिका में साबित किए गए XOR प्रदान करेगा।

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

मैं इस दृष्टिकोण पर प्रदर्शन नहीं खोद रहा हूँ: quick-bench.com/PgNgGN8ATrKt7el1dAaJj7QtuF4
xaxxon

इसके बारे में रक्षात्मक होने की कोई आवश्यकता नहीं है।
xaxxon

1
@xaxxon: इस बेंचमार्क में बिंदु नहीं देखें !? StringCreation में आपने स्ट्रिंग के निर्माण में उपयोग किया, लेकिन दूसरे बेंचमार्क में आपने नहीं किया। यदि आप दोनों बेंचमार्क में समान कोड रखते हैं, और प्रत्येक बेंचमार्क (XOR, और XOR2) के लिए अलग-अलग XOR को कॉल करते हैं, तो आपको समान बेंचमार्क परिणाम मिलते हैं। तो आप क्या कहना चाह रहे हैं?
19

1

मैं "xor" का उपयोग करता हूं (ऐसा लगता है कि यह एक कीवर्ड है; कोड में: कम से कम यह बोल्ड हो जाता है) जैसे आप "और" के बजाय &&"और" या "के बजाय" का उपयोग कर सकते हैं ||

if (first xor second)...

हां, यह बिटवाइस है। माफ़ करना।


2
मैं अनुमान लगा रहा हूं कि वे कहीं से #defines छिपे हुए हैं। मुझे पूरा यकीन है "और" और "xor" एएनएसआई सी में कीवर्ड नहीं हैं ... (कम से कम
C79

1
@ ब्रायन पोस्टो: मुझे नहीं पता कि C79 क्या है, लेकिन C ++ 98 में andऔर xorमानक पुस्तकालय मैक्रोज़ हैं। थाय "कहीं" से नहीं हैं, वे <iso646.h> से हैं। ये मैक्रोज़ C99 (C89 / 90 के बारे में निश्चित नहीं) में भी हैं।
अपराह्न

5
@Brian Postow: ... xorके लिए खड़ा है बिटवाइज़ , XOR हालांकि, जबकि andहै तार्किक और।
एनटी

1
मैंने C89 को C79 के रूप में गलत समझा और ... और xor इत्यादि K & R की कॉपी में नहीं हैं। मुझे नहीं लगता कि मैंने कभी iso686.h का उपयोग किया है, कम से कम जानबूझकर नहीं ... और हां, वे कहीं से #defines हैं, आपको बस यह पता होना चाहिए कि कहीं बी
ब्रायन पोस्टो

2
वे निश्चित रूप से उस हेडर का उपयोग करके C99 में हैं। C ++ में, उन्हें भाषा में "वैकल्पिक टोकन" के रूप में एकीकृत किया गया है, और आप struct A { compl A() { } };उदाहरण के लिए, एक विध्वंसक को परिभाषित करने के लिए कर सकते हैं ।
जोहान्स शाउब -

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

यह परिभाषित के रूप में काम करता है। सशर्त यह पता लगाने के लिए हैं कि क्या आप ऑब्जेक्टिव-सी का उपयोग कर रहे हैं , जो बूल के बजाय BOOL के लिए पूछ रहा है (लंबाई अलग है!)


3
यह डबल अंडरस्कोर नियम का उल्लंघन करता है।
तमसे सजेलेई

@ TamásSzelei जरूरी नहीं कि कंपाइलर यह नहीं देखता है कि जैसा कि यह पूर्ववर्ती था, और उद्देश्य-सी दुनिया में डबल अंडरस्कोर काफी आम हैं।
मैक्सथन चान

प्रीप्रोसेसर के बारे में अच्छी बात है, हालांकि मेरे लिए यह अभी भी इस तरह से कोड गंध है (वैसे भी एक मैक्रो का उपयोग क्यों करें?)। साथ ही सवाल ऑब्जेक्टिव-सी के बारे में नहीं था।
तमसे सजेलेई

@ TamásSzelei वैसे मुझे कई भाषाओं में हेडर फ़ाइलों को साझा करने की आदत है, और आमतौर पर सभी हेडर ऑब्जेक्टिव-सी से आते हैं। मेरे नए कोड में अभी बहुत अधिक गंध नहीं है, लेकिन डबल अंडरस्कोर अभी भी समय-समय पर ओब्जेक्ट आदतों का पालन करने के लिए उपयोग किया जाता है।
मैक्सथन चान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.