सी

2009-12-07 9 views
22

में नकारात्मक संख्याओं को सही स्थानांतरित करना मेरे पास सी कोड है जिसमें मैं निम्नलिखित करता हूं।सी

int nPosVal = +0xFFFF; // + Added for ease of understanding 
int nNegVal = -0xFFFF; // - Added for valid reason 

अब मैं

printf ("%d %d", nPosVal >> 1, nNegVal >> 1); 

जब कोशिश मैं

32767 -32768 

इस उम्मीद है?

मैं की तरह

65535 >> 1 = (int) 32767.5 = 32767 
-65535 >> 1 = (int) -32767.5 = -32768 

है यही कारण है कि कुछ सोचने के लिए सक्षम हूँ, -३२७६७.५ -32,768 के लिए रवाना गोल है।

क्या यह समझ सही है?

उत्तर

32

ऐसा लगता है कि अपने कार्यान्वयन शायद दो के पूरक संख्या के साथ एक गणित सा बदलाव कर रही है। इस प्रणाली में, यह सभी बिट्स को दाईं ओर बदल देता है और फिर अंतिम बिट्स की एक प्रति के साथ ऊपरी बिट्स में भर जाता है। तो अपने उदाहरण के लिए, इलाज पूर्णांक 32-बिट यहाँ के रूप में:

nPosVal = 00000000000000001111111111111111 
nNegVal = 11111111111111110000000000000001 

पारी के बाद, आप मिल गया है:

nPosVal = 00000000000000000111111111111111 
nNegVal = 11111111111111111000000000000000 

आप दशमलव को यह वापस परिवर्तित, तो आप प्राप्त कर 32767 और -32,768 क्रमशः।

प्रभावी रूप से, नकारात्मक अनंतता की ओर एक सही शिफ्ट राउंड।

संपादित करें:

की E1 >> E2 परिणाम है E1 सही-स्थानांतरित E2 बिट पदों: धारा नवीनतम draft standard के 6.5.7 के अनुसार, ऋणात्मक संख्याओं पर इस व्यवहार कार्यान्वयन निर्भर है। E1 एक अहस्ताक्षरित प्रकार है या यदि E1 एक हस्ताक्षरित प्रकार और ग़ैर-ऋणात्मक मान होता है, परिणाम का मूल्य E1/2 E2 के भागफल का अभिन्न अंग है। यदि ई 1 के पास एक हस्ताक्षरित प्रकार और ऋणात्मक मान है, तो परिणामी मान कार्यान्वयन-परिभाषित है।

उनकी घोषित rational इस के लिए:

C89 समिति का विस्तार, के बाद से इस तरह के एक आवश्यकता तेजी से कोड को धीमा हो सकता है पर हस्ताक्षर करने पर हस्ताक्षर किए सही पारी आपरेशन की जरूरत नहीं में और उपयोगिता के बाद से कश्मीर & आर द्वारा दी गई कार्यान्वयन में स्वतंत्रता की पुष्टि की साइन विस्तारित बदलावों का मामूली है। (एक नकारात्मक दो के पूरक पूर्णांक स्थानांतरण हिसाब से सही एक ही स्थान पर नहीं दो से विभाजित के रूप में ही है!)

तो यह कार्यान्वयन सिद्धांत रूप में निर्भर है। प्रैक्टिस में, मैंने कभी भी कार्यान्वयन नहीं देखा है बाएं ऑपरेंड पर हस्ताक्षर किए जाने पर अंकगणितीय शिफ्ट करें।

+0

+1, जो मैं जानना चाहता था। नकारात्मक शिफ्ट की ओर सही शिफ्ट राउंड। लेकिन क्या यह दस्तावेज है? – Alphaneo

+0

यह कार्यान्वयन निर्भर है। (उपरोक्त मेरा संपादन देखें।) जैसा कि मैंने कहा था, मैंने कभी भी इस पर एक कार्यान्वयन अलग नहीं देखा है, लेकिन यह सैद्धांतिक रूप से कर सकता है। – Boojum

2

जब आप सही-स्थानांतरित करते हैं, तो कम से कम महत्वपूर्ण-बिट को त्याग दिया जाता है।

0xFFFF = 0 1111 1111 1111 1111, जो सही-बदलाव देने के लिए 0 0111 1111 1111 1111 = 0x7FFF

-0xFFFF = 1 0000 0000 0000 0001 (2s पूरक) है, जो सही-बदलाव 1 1000 0000 के लिए 0000 0000 = -0x8000

7

सी विनिर्देश निर्दिष्ट नहीं करता है कि साइन बिट को स्थानांतरित किया गया है या नहीं। यह कार्यान्वयन निर्भर है।

+0

मुझे लगता है कि उसकी समस्या है पर विश्वास नहीं करते ... – rlbond

+0

क्यू 1 से पूछा कि क्या परिणाम की उम्मीद थी। मेरा जवाब बताता है कि नहीं, आप अपने कंपाइलर्स प्रलेखन से पहले परामर्श किए बिना ऋणात्मक संख्या के सही बदलाव के लिए किसी दिए गए परिणाम की उम्मीद नहीं कर सकते – Trent

+0

क्या आप मुझे एक लिंक दे सकते हैं, जहां मानक ऐसा कहता है? – hirschhornsalz

3

ए -1: हाँ। 0xffff >> 1 0x7fff या 32767 है। मुझे यकीन नहीं है कि -0xffff क्या करता है। यह अनोखा है।

ए -2: स्थानांतरण स्थानांतरण के समान नहीं है। यह थोड़ा स्थानांतरण है - एक प्राचीन बाइनरी ऑपरेशन। कभी-कभी किसी प्रकार के विभाजन के लिए इसका उपयोग किया जा सकता है, लेकिन हमेशा समान नहीं होता है।

+0

पूर्णांक शाब्दिक ints पर हस्ताक्षर किए हैं, इसलिए '- 0xFFFF' नकारता' 0xFFFF'। यही है, यह '(~ 0xFFFF) -1' के बराबर है, जिसे एक हस्ताक्षरित पूर्णांक के रूप में व्याख्या किया गया है। – outis

18

नहीं, आपको पूर्णांक के साथ काम करते समय 0.5 जैसे अंशकालिक संख्याएं नहीं मिलती हैं। परिणाम आसानी से समझाया जा सकता है जब आप दो संख्याओं का बाइनरी अभ्यावेदन पर नज़र डालें:

 65535: 00000000000000001111111111111111 
    -65535: 11111111111111110000000000000001 

बिट सही एक बिट के लिए स्थानांतरण, और बाएँ पर विस्तार (ध्यान रखें कि इस कार्यान्वयन निर्भर है धन्यवाद ट्रेंट):

65535 >> 1: 00000000000000000111111111111111 
-65535 >> 1: 11111111111111111000000000000000 

Convert वापस दशमलव रहे हैं:

65535 >> 1 = 32767 
-65535 >> 1 = -32768 
+6

ध्यान दें कि बाईं तरफ विस्तार करना कार्यान्वयन निर्भर है। – Trent

+2

मानक कहता है: "यदि दाएं ऑपरेंड का मान नकारात्मक है या प्रचारित बाएं ऑपरेंड की चौड़ाई से अधिक या बराबर है, तो व्यवहार अपरिभाषित है।" – Gonzalo

+0

@ ट्रेंट: क्या आप निश्चित हैं? मैंने सोचा कि साइन एक्सटेंशन बाएं ऑपरेंड की हस्ताक्षर पर निर्भर करता है। – hirschhornsalz

2

सी स्तर के नीचे, मशीनों में एक सीपीयू कोर होता है जो पूरी तरह से पूर्णांक या स्केलर है। हालांकि इन दिनों प्रत्येक डेस्कटॉप सीपीयू में एक एफपीयू है, यह हमेशा मामला नहीं था और आज भी एम्बेडेड सिस्टम बिना फ्लोटिंग पॉइंट निर्देशों के बने होते हैं।

आज की प्रोग्रामिंग मानदंड और सीपीयू डिजाइन और भाषाओं युग में जहाँ एफपीयू भी मौजूद नहीं हो सकता है से की तारीख।

तो, सीपीयू निर्देश तय बिन्दु आपरेशनों, आम तौर पर विशुद्ध रूप से पूर्णांक ऑप्स के रूप में इलाज को लागू। सिर्फ अगर एक कार्यक्रम नाव के आइटम वाणी या डबल किसी भी अंशों उपलब्ध नहीं होगा। (ठीक है, आप सीपीयू ओप का उपयोग अंशों के साथ "निश्चित बिंदु" के लिए कर सकते हैं लेकिन यह अब और हमेशा दुर्लभ था।)

कई साल पहले एक भाषा मानक समिति द्वारा आवश्यकतानुसार, सभी उचित मशीनें संकेत प्रसारित करती हैं हस्ताक्षरित संख्याओं के सही बदलाव पर थोड़ा सा। बिना हस्ताक्षर किए गए मानों की सही बदलाव बाईं ओर शून्य में स्थानांतरित होती है। दाहिने ओर स्थानांतरित बिट्स फर्श पर गिराए गए हैं।

अपनी समझ को आगे करने के लिए आप "दुक्की-पूरक गणित" की जांच करने की आवश्यकता होगी।

+0

मुझे लगता है कि "उचित मशीन" की आपकी परिभाषा एक संकीर्ण है। – Trent

+0

यदि मेरी परिभाषा संकीर्ण है तो कृपया एक मशीन का नाम दें जिसके लिए सी में 'x >> 1', नकारात्मक संख्या को सकारात्मक में बदल देगा। – DigitalRoss

+0

माइक्रोचिप सी 18 कंपाइलर (उपयोगकर्ता मार्गदर्शिका का एक लिंक यहां पाया जा सकता है: http://tinyurl.com/ybt2svs - अनुभाग बी.4 देखें) – Trent