2008-09-15 8 views
55

यह जांचने का सबसे आसान तरीका है कि दो पूर्णांकों का एक ही संकेत है या नहीं? क्या ऐसा करने के लिए कोई छोटी सी चीज है?जांचने के लिए सबसे आसान तरीका है कि दो पूर्णांकों का एक ही संकेत है या नहीं?

उत्तर

42

यहाँ एक संस्करण है कि C/C++ कि पूर्णांक आकार पर निर्भर नहीं करता या अतिप्रवाह समस्या है में काम करता है (यानी x * y> = 0 काम नहीं करता है)

bool SameSign(int x, int y) 
{ 
    return (x >= 0)^(y < 0); 
} 
बेशक

है, तुम बाहर रुचि है और टेम्पलेट कर सकते हैं:

template <typename valueType> 
bool SameSign(typename valueType x, typename valueType y) 
{ 
    return (x >= 0)^(y < 0); 
} 

नोट: जब से हम अनन्य उपयोग कर रहे हैं या, हम शून्य के खिलाफ इस प्रकार विभिन्न जांच जब संकेत ही हैं एलएचएस और आरएचएस अलग होना चाहते हैं।

+1

काफी अच्छा, मेरे अंदर सी/सी ++ हैकर पूरी तरह से इस कोड स्निपेट का समर्थन करता है। मेरे में सॉफ़्टवेयर इंजीनियर सवाल करता है कि उपयोगकर्ता को इस तरह के सामान्य तरीके से क्यों पता होना चाहिए! – user7116

+0

क्या यह विफल नहीं होता है यदि x = 0 और y> 0? –

2

अगर (एक्स * वाई)> 0 ...

संभालने गैर शून्य और इस तरह के।

1

बस मेरे सिर के ऊपर से ...

int mask = 1 << 31; 
(a & mask)^(b & mask) < 0; 
+0

केवल –

0

अगर (एक * ख < 0) पर हस्ताक्षर अलग है, और संकेत में ही है (या एक या ख है शून्य)

+0

में निर्धारित नहीं किया गया था अतिप्रवाह –

6

मान लिया जाये कि 32 बिट ints:

bool same = ((x^y) >> 31) != 1; 

थोड़ा अधिक संक्षिप्त:

bool same = !((x^y) >> 31); 
+2

उन दो कोड उदाहरण हमेशा हमेशा हमेशा एक कोड टिप्पणी कृपया से पहले किया जाना चाहिए के लिए काम नहीं करता लिए काम करता है । वास्तविक जीवन में, मैं शायद कुछ इसी तरह का उपयोग करूंगा = Math.Sign (x) == Math.Sign (y)। जब लोग उन्हें पूछते हैं तो मैं सिर्फ बुराई देता हूं। : डी –

+3

ओह, निश्चित रूप से (वास्तविक जीवन में) 32 बिट ints, जो सवाल – Patrick

+1

उम, यह मान्य कोड नहीं है ... आप कैसे काम करने के लिए '& >>' की अपेक्षा करते हैं? –

0

अधिकांश मशीन प्रस्तुतियों में, मेरे विश्वविद्यालय के दिनों में वापस सोचना, एक पूर्णांक का बायां-सबसे छोटा नहीं है जब संख्या ऋणात्मक है, और 0 जब यह सकारात्मक है?

मुझे लगता है कि यह मशीन-निर्भर है, हालांकि।

4

(integer1 * Integer2)> 0

क्योंकि जब दो पूर्णांकों एक संकेत का हिस्सा, गुणन का परिणाम हमेशा सकारात्मक हो जाएगा।

यदि आप 0 को एक ही संकेत के रूप में व्यवहार करना चाहते हैं तो आप इसे भी बना सकते हैं।

+2

केवल उत्पाद ओवरफ्लो तक काम करता है। – Frosty

+1

भी, गुणा धीमा हो सकता है ... –

+0

यदि पूर्णांक में से कोई एक 0 है, तो आपको कोई समस्या है। – TatiOverflow

0

int same_sign =! ((X >> 31)^(y >> 31));

अगर (same_sign) ... बाकी ...

2

एक तकनीकी नोट के रूप में, थोड़ा-twiddly समाधान गुणा से अधिक योग्य होने के लिए, यहां तक ​​कि आधुनिक आर्किटेक्चर पर जा रहे हैं। यह केवल बारे में 3 चक्र है कि आप को सहेज रहे हैं, लेकिन आप जानते हैं कि वे एक "बचाया पैसा" के बारे में क्या कहते हैं ...

+5

बचाया गया एक पैसा सभी बुराइयों की जड़ है, लगभग 9 7% समय कहता है? – ysth

18
(a^b) >= 0 

1 करने के लिए मूल्यांकन करेंगे, तो संकेत एक ही है, अन्यथा 0 है।

+0

ओह, अच्छा! :-) मुझे आश्चर्य है कि मुझे यह याद आया। इस समाधान के बारे में वास्तव में अच्छी बात यह है कि यह अंतर्निहित पूर्णांक प्रतिनिधित्व में किसी विशेष बिट कार्डिनालिटी पर निर्भर नहीं है। –

+1

यह एक आनंददायक कॉम्पैक्ट "xorl% edi,% esi; x% पर सेट% al", केवल 6 बाइट्स और दो निर्देशों में परिणाम देता है। यह एक दिलचस्प मामला अध्ययन भी है क्योंकि यह एक ठोस मामला है जहां एक int के बजाय 'बूल' लौटने से नाटकीय रूप से बेहतर कोड उत्पन्न होता है। –

+0

@ जॉन मैचैम: यह सोचकर कि आपका क्या मतलब है 'यह एक ठोस मामला है जहां एक इंट के बजाए' बूल 'लौटने से नाटकीय रूप से बेहतर कोड' –

11

मैं पूर्णांक के संकेत को निर्धारित करने के लिए किसी भी बिटवाई चाल से सावधान रहूंगा, तब आपको यह मानना ​​होगा कि उन संख्याओं को आंतरिक रूप से कैसे प्रदर्शित किया जाता है।

लगभग 100% समय, पूर्णांक two's compliment के रूप में संग्रहीत किए जाएंगे, लेकिन सिस्टम के आंतरिक के बारे में धारणाएं करने के लिए यह अच्छा अभ्यास नहीं है जबतक कि आप एक डेटाटाइप का उपयोग नहीं कर रहे हैं जो एक विशेष स्टोरेज प्रारूप को गारेन करता है।

दो की तारीफ में, आप यह निर्धारित करने के लिए पूर्णांक में अंतिम (बाएं-सबसे) बिट की जांच कर सकते हैं कि यह नकारात्मक है, तो आप इन दोनों बिट्स की तुलना कर सकते हैं। इसका मतलब यह होगा कि 0 के पास सकारात्मक संख्या के समान संकेत होगा, जो अधिकांश भाषाओं में लागू साइन फ़ंक्शन के साथ बाधाओं में है।

व्यक्तिगत रूप से, मैं बस आपकी चुनी भाषा के साइन फ़ंक्शन का उपयोग करता हूं। यह असंभव है कि इस तरह की गणना के साथ कोई प्रदर्शन समस्या होगी।

+0

उत्पन्न होता है, साथ ही, ये चालें पठनीयता कम करती हैं। – hop

+1

सी मानक लिब एक signbit() फ़ंक्शन प्रदान करता है। अपने स्वयं के devising के किसी भी "bitwise चाल" के साथ optimiser को हरा करने के लिए शायद मुश्किल है। – hop

1

दो के पूरक गणित के साथ int की किसी भी आकार के लिए:

#define SIGNBIT (~((unsigned int)-1 >> 1)) 
if ((x & SIGNBIT) == (y & SIGNBIT)) 
    // signs are the same 
1

संभालने 32 बिट

अगर (((x^y) & 0x80000000) == 0)

... उत्तर अगर (x * y> 0) अतिप्रवाह

5

के कारण खराब है, तो मुझे सच में यकीन नहीं है कि मैं समानार्थी होने के लिए "bitwise चाल" और "सरल" मानता हूं। मुझे बहुत सारे उत्तर दिखाई देते हैं जो 32-बिट पूर्णांक पर हस्ताक्षर कर रहे हैं (हालांकि यह बेकार होने के लिए मूर्खतापूर्ण होगा); मुझे यकीन नहीं है कि वे फ्लोटिंग-पॉइंट मानों पर लागू होंगे।

ऐसा लगता है कि "सरलतम" जांच की तुलना करना होगा कि दोनों मान 0 से कैसे तुलना करते हैं; यह बहुत सामान्य है कि इस प्रकार की तुलना की जा सकती है:

bool compare(T left, T right) 
{ 
    return (left < 0) == (right < 0); 
} 

यदि संकेत विपरीत हैं, तो आप झूठे होते हैं। यदि संकेत समान हैं, तो आप सच हो जाते हैं।

+0

झूठी और झूठी == झूठी मुझे डर है कि आपको इसे सही बनाने के लिए XOR की अस्वीकृति करने की आवश्यकता होगी। –

187

क्या

return ((x<0) == (y<0)); 

साथ गलत क्या है?

inline bool same_sign(int x, int y) { 
    return (x^y) >= 0; 
} 

यह अनुकूलन के साथ एक आधुनिक प्रोसेसर पर दिए गए निर्देशों के रूप में छोटे रूप में दो 1ns से और कम ले जा सकते हैं:

+21

उम ... कुछ भी नहीं ... दुख की बात है कि हम सभी ने सरल समाधान को याद किया। – Torlack

+0

महान उत्तर, सादगी अद्भुत है। –

+1

साइन किए गए शून्य के बारे में क्या। -0.0 बनाम बिना हस्ताक्षर किए गए शून्य 0.0 –

4

मान लिया जाये कि दुक्की अंकगणित (http://en.wikipedia.org/wiki/Two_complement) के पूरक हैं।

inline bool same_sign(int x, int y) { 
    return (x<0) == (y<0); 
} 

यह एक या दो अतिरिक्त निर्देश की आवश्यकता होती है और एक छोटे से अधिक समय लग सकता:

संभालने नहीं दुक्की गणित के पूरक हैं।

गुणा का उपयोग करना एक बुरा विचार है क्योंकि यह अतिप्रवाह के लिए कमजोर है।

+0

1 और 0 दोनों कार्यों के लिए सच हो रहा है ... – matias

+1

@matias जैसा इसे करना चाहिए। 0 और 1 का एक ही संकेत है। इंटीग्रर्स के पास नकारात्मक 0 नहीं है। –

+0

स्पष्ट रूप से आप सही हैं मैं पूरी तरह से मस्तिष्क farted – matias

1

शाखा सी संस्करण:

int sameSign(int a, int b) { 
    return ~(a^b) & (1<<(sizeof(int)*8-1)); 
} 

सी ++ पूर्णांक प्रकार के लिए टेम्पलेट:

template <typename T> T sameSign(T a, T b) { 
    return ~(a^b) & (1<<(sizeof(T)*8-1)); 
} 
0

बेहतर तरीका इस प्रकार std::signbit का उपयोग कर:

std::signbit(firstNumber) == std::signbit(secondNumber); 

यह भी अन्य बुनियादी प्रकार का समर्थन (double , float, char आदि)।

संबंधित मुद्दे

 संबंधित मुद्दे