क्या ((a + (b & 255)) और 255) ((a + b) & 255) के समान है?


92

मैं कुछ C ++ कोड ब्राउज़ कर रहा था, और कुछ इस तरह पाया:

(a + (b & 255)) & 255

डबल और मुझे गुस्सा आया, तो मैंने सोचा:

(a + b) & 255

( aऔर b32-बिट अहस्ताक्षरित पूर्णांक हैं)

मैंने अपने सिद्धांत की पुष्टि करने के लिए जल्दी से एक परीक्षण स्क्रिप्ट (JS) लिखी:

for (var i = 0; i < 100; i++) {
    var a = Math.ceil(Math.random() * 0xFFFF),
        b = Math.ceil(Math.random() * 0xFFFF);

    var expr1 = (a + (b & 255)) & 255,
        expr2 = (a + b) & 255;

    if (expr1 != expr2) {
        console.log("Numbers " + a + " and " + b + " mismatch!");
        break;
    }
}

हालांकि स्क्रिप्ट ने मेरी परिकल्पना की पुष्टि की (दोनों ऑपरेशन समान हैं), मुझे अभी भी इस पर भरोसा नहीं है, क्योंकि 1) यादृच्छिक और 2) मैं गणितज्ञ नहीं हूं, मुझे नहीं पता कि मैं क्या कर रहा हूं

इसके अलावा, लिस्प-वाई शीर्षक के लिए क्षमा करें। इसे संपादित करने के लिए स्वतंत्र महसूस करें।


4
वह लिपि कौन सी भाषा है? क्या Math.random()पूर्णांक या एक डबल पर [0,1) लौटाता है? मुझे नहीं लगता कि आपकी स्क्रिप्ट (सबसे अच्छी जो मैं बता सकता हूं) उस समस्या को दर्शाती है जिसे आपने बिल्कुल भी प्रस्तुत किया है।
ईंट

7
C / c ++ कोड क्या है? वे अलग-अलग भाषाएं हैं।
वेन वेन

14
आप उस व्यवहार को पुन: पेश नहीं कर सकते, जिसे आप JS में परखना चाहते हैं। इसलिए हर कोई केवल आपके लिए भाषा की पसंद है। JS दृढ़ता से टाइप नहीं किया गया है और उत्तर C / C ++ में चर के प्रकार पर गंभीर रूप से निर्भर करता है। जेएस पूरा बकवास है जिसे आपने पूछा है।
ईंट

4
जावास्क्रिप्ट फ़ंक्शन नाम का उपयोग करके आवश्यक है कि छद्म कोड आवश्यक है। उनका सवाल के व्यवहार के बारे में है &और +C और C ++ में अहस्ताक्षरित पूर्णांकों पर।
बारमर

11
ध्यान रखें कि "मैंने एक परीक्षण कार्यक्रम लिखा था और मुझे उत्तर मिला कि मुझे सभी संभावित आदानों की उम्मीद थी" वास्तव में कोई गारंटी नहीं है कि कुछ ऐसा व्यवहार करता है जो आप अपेक्षा करते हैं। अपरिभाषित व्यवहार उस तरह बुरा हो सकता है; केवल अनपेक्षित परिणाम देने के बाद आप अपने आप को आश्वस्त करते हैं कि आपका कोड सही है।

जवाबों:


78

वह एक जैसे है। यहाँ एक सबूत है:

सबसे पहले पहचान पर ध्यान दें (A + B) mod C = (A mod C + B mod C) mod C

के a & 255रूप में के रूप में खड़े के बारे में समस्या को शांत करते हैं a % 256। यह तब से सही है जब तक aअहस्ताक्षरित नहीं है।

तो (a + (b & 255)) & 255है(a + (b % 256)) % 256

यह वैसा ही है (a % 256 + b % 256 % 256) % 256(मैंने ऊपर बताई गई पहचान लागू की है: ध्यान दें कि modऔर %अहस्ताक्षरित प्रकारों के लिए समान हैं।)

यह सरल (a % 256 + b % 256) % 256हो जाता है (a + b) % 256(पहचान को फिर से लागू करना)। फिर आप बिटवाइज़ ऑपरेटर को वापस देने के लिए रख सकते हैं

(a + b) & 255

प्रमाण पूरा करना।


81
अतिप्रवाह की संभावना को नजरअंदाज करते हुए यह गणितीय प्रमाण है। विचार करें A=0xFFFFFFFF, B=1, C=3। पहली पहचान नहीं है। (ओवरफ्लो अहस्ताक्षरित अंकगणित के लिए एक समस्या नहीं होगी, लेकिन यह थोड़ी अलग बात है।)
एलेक्सडी

4
दरअसल, (a + (b & 255)) & 255वही है (a + (b % 256)) % N % 256, जहां Nअधिकतम अहस्ताक्षरित मूल्य से एक बड़ा है। (बाद वाले सूत्र का अर्थ गणितीय पूर्णांकों के अंकगणित के रूप में माना जाता है)

17
इस तरह के गणितीय प्रमाण कंप्यूटर आर्किटेक्चर पर पूर्णांक के व्यवहार को साबित करने के लिए उपयुक्त नहीं हैं।
जैक एडले

25
@ जैकएडली: सही तरीके से किए जाने पर वे उपयुक्त हैं (जो एक नहीं है, अतिप्रवाह पर विचार करने की उपेक्षा के कारण)।

3
@ शाज: यह टेस्ट स्क्रिप्ट का सच है, लेकिन पूछे गए सवाल का हिस्सा नहीं है।

21

स्थितिबद्ध जोड़ के अलावा, अहस्ताक्षरित परिणामों को उत्पन्न करने के लिए अहस्ताक्षरित संख्याओं का घटाव और गुणा, इनपुट के अधिक महत्वपूर्ण अंक परिणाम के कम-महत्वपूर्ण अंकों को प्रभावित नहीं करते हैं। यह द्विआधारी अंकगणित पर लागू होता है जितना कि दशमलव अंकगणित पर होता है। यह हस्ताक्षरित अंकगणित पर "ट्वोस सप्लीमेंट" पर भी लागू होता है, लेकिन हस्ताक्षरित अंकगणित पर हस्ताक्षर करने के लिए नहीं।

हालाँकि, बाइनरी अंकगणित से नियम लेने और उन्हें C पर लागू करने के दौरान हमें सावधान रहना होगा (I beleive C ++ में इस सामान पर C के समान नियम हैं लेकिन मुझे 100% यकीन नहीं है) क्योंकि C अंकगणित में कुछ रहस्यमय नियम हैं जो हमें यात्रा कर सकते हैं यूपी। C में बिना लिखा अंकगणित सरल बाइनरी रैपपराउंड नियमों का पालन करता है लेकिन हस्ताक्षरित अंकगणित अतिप्रवाह अपरिभाषित व्यवहार है। कुछ परिस्थितियों में बदतर C स्वचालित रूप से (हस्ताक्षरित) int को एक अहस्ताक्षरित प्रकार को "बढ़ावा" देगा।

सी में अपरिभाषित व्यवहार विशेष रूप से कपटी हो सकता है। एक डंब कंपाइलर (या कम अनुकूलन स्तर पर एक कंपाइलर) बाइनरी अंकगणित की आपकी समझ के आधार पर वह करने की संभावना है, जबकि एक अनुकूलन कंपाइलर आपके कोड को अजीब तरीके से तोड़ सकता है।


तो सवाल में सूत्र को वापस प्राप्त करना समरूपता ऑपरेंड प्रकारों पर निर्भर करता है।

यदि वे अहस्ताक्षरित पूर्णांक हैं, जिनका आकार आकार से अधिक या उसके बराबर है, intतो अतिरिक्त ऑपरेटर के अतिप्रवाह व्यवहार को सरल बाइनरी रैपपाउंड के रूप में अच्छी तरह से परिभाषित किया गया है। अतिरिक्त संचालन के परिणाम के कम बिट्स पर कोई प्रभाव नहीं होने से पहले हम एक ऑपरेंड के उच्च 24 बिट्स को बंद करते हैं या नहीं।

यदि वे अहस्ताक्षरित पूर्णांक हैं जिनके आकार से कम है intतो उन्हें पदोन्नत (हस्ताक्षरित) किया जाएगा int। हस्ताक्षर किए गए पूर्णांकों का अतिप्रवाह अपरिभाषित व्यवहार है, लेकिन कम से कम प्रत्येक प्लेटफ़ॉर्म पर मैंने विभिन्न पूर्णांक प्रकारों के बीच आकार में अंतर का सामना किया है, यह पर्याप्त है कि दो पदोन्नत मूल्यों के एकल जोड़ के अतिप्रवाह का कारण नहीं होगा। इसलिए फिर से हम बयानों को बराबर समझने के लिए बस बाइनरी अंकगणितीय तर्क पर वापस आ सकते हैं।

यदि वे पूर्णांक पर हस्ताक्षर किए जाते हैं, जिसका आकार इंट से कम है, तो फिर से अतिप्रवाह नहीं हो सकता है और दो-पूरक कार्यान्वयन पर हम मानक बाइनरी अंकगणितीय तर्क पर भरोसा कर सकते हैं कि वे समतुल्य हैं। साइन-परिमाण या लोगों के क्रियान्वयन के पूरक के रूप में वे समतुल्य नहीं होंगे।

OTOH यदि aऔर bपूर्णांक पर हस्ताक्षर किए गए थे जिनका आकार इंट के आकार से अधिक या बराबर था, तो भी दो पूरक कार्यान्वयन पर ऐसे मामले हैं जहां एक बयान को अच्छी तरह से परिभाषित किया जाएगा जबकि दूसरा अपरिभाषित व्यवहार होगा।


20

Lemma: a & 255 == a % 256अहस्ताक्षरित के लिए a

अहस्ताक्षरित aके रूप में लिखा जा सकता है m * 0x100 + bकुछ अहस्ताक्षरित m, b, 0 <= b < 0xff, 0 <= m <= 0xffffff। यह दोनों परिभाषाओं से अनुसरण करता है a & 255 == b == a % 256

इसके अतिरिक्त, हमें आवश्यकता है:

  • वितरण संपत्ति: (a + b) mod n = [(a mod n) + (b mod n)] mod n
  • अहस्ताक्षरित जोड़ की परिभाषा, गणितीय रूप से: (a + b) ==> (a + b) % (2 ^ 32)

इस प्रकार:

(a + (b & 255)) & 255 = ((a + (b & 255)) % (2^32)) & 255      // def'n of addition
                      = ((a + (b % 256)) % (2^32)) % 256      // lemma
                      = (a + (b % 256)) % 256                 // because 256 divides (2^32)
                      = ((a % 256) + (b % 256 % 256)) % 256   // Distributive
                      = ((a % 256) + (b % 256)) % 256         // a mod n mod n = a mod n
                      = (a + b) % 256                         // Distributive again
                      = (a + b) & 255                         // lemma

तो हाँ, यह सच है। 32-बिट अहस्ताक्षरित पूर्णांकों के लिए।


अन्य पूर्णांक प्रकारों के बारे में क्या?

  • 64-बिट अहस्ताक्षरित पूर्णांकों के लिए, उपरोक्त सभी लागू होता है, बस के 2^64लिए प्रतिस्थापित करता है 2^32
  • 8- और 16-बिट अहस्ताक्षरित पूर्णांक के लिए, इसके अलावा पदोन्नति शामिल है int। यह intनिश्चित रूप से इन कार्यों में से किसी में भी अतिप्रवाह या नकारात्मक नहीं होगा, इसलिए वे सभी वैध रहेंगे।
  • के लिए हस्ताक्षर किए पूर्णांक, अगर या तो a+bया a+(b&255)अतिप्रवाह, यह अपरिभाषित व्यवहार है। तो समानता पकड़ नहीं सकती है - ऐसे मामले हैं जहां (a+b)&255अपरिभाषित व्यवहार होता है लेकिन (a+(b&255))&255ऐसा नहीं है।

17

हाँ, (a + b) & 255ठीक है।

स्कूल में जोड़ याद है? आप अंकों को अंकों से जोड़ते हैं, और अंकों के अगले कॉलम में कैरी वैल्यू जोड़ते हैं। पहले से संसाधित कॉलम को प्रभावित करने के लिए अंकों के बाद के (अधिक महत्वपूर्ण) कॉलम के लिए कोई रास्ता नहीं है। इस वजह से, यदि आप केवल परिणाम में अंकों को शून्य-आउट करते हैं, या पहले एक तर्क में भी इसका कोई फर्क नहीं पड़ता है।


उपरोक्त हमेशा सच नहीं होता है, सी ++ मानक एक कार्यान्वयन की अनुमति देता है जो इसे तोड़ देगा।

इस तरह के डेथस्टेशन 9000 : - ) को 33-बिट का उपयोग करना होगा int, अगर ओपी का मतलब unsigned short"32-बिट अहस्ताक्षरित पूर्णांक" से है। अगर unsigned intमतलब होता है, तो DS9K को 32-बिट का उपयोग करना होगा int, और 32-बिट unsigned intको पैडिंग बिट के साथ। (अहस्ताक्षरित पूर्णांक का आकार part3.9.1 / 3 के अनुसार उनके हस्ताक्षरित समकक्षों के समान होना आवश्यक है, और पैडिंग बिट्स को .93.9.1 / 1 में अनुमति दी गई है।) आकार और पैडिंग बिट्स के अन्य संयोजन भी काम करेंगे।

जहाँ तक मैं बता सकता हूँ, यह इसे तोड़ने का एकमात्र तरीका है, क्योंकि:

  • पूर्णांक प्रतिनिधित्व को "विशुद्ध रूप से द्विआधारी" एन्कोडिंग योजना (.13.9.1 / 7 और फ़ुटनोट) का उपयोग करना चाहिए, पैडिंग बिट्स को छोड़कर सभी बिट्स और साइन बिट को 2 n के मूल्य में योगदान करना चाहिए
  • int पदोन्नति की अनुमति केवल तभी दी जाती intहै जब स्रोत प्रकार (/4.5 / 1) के सभी मूल्यों का प्रतिनिधित्व कर सकते हैं, इसलिए intमूल्य में कम से कम 32 बिट्स का योगदान होना चाहिए, साथ ही एक साइन बिट।
  • intअधिक मूल्य बिट्स हो सकता है नहीं 32 से (साइन बिट गिनती नहीं), क्योंकि किसी एक अतिरिक्त अतिप्रवाह नहीं कर सकता।

2
इसके अलावा कई अन्य ऑपरेशन हैं जहां उच्च बिट्स में कचरा कम बिट्स में परिणाम को प्रभावित नहीं करता है जिसमें आप रुचि रखते हैं। इस प्रश्नोत्तर को 2 के पूरक के रूप में देखें , जो x86 asm का उपयोग-केस के रूप में करता है, लेकिन यह भी लागू होता है किसी भी स्थिति में बिना बाइनरी पूर्णांक।
पीटर कॉर्ड्स

2
हालांकि यह निश्चित रूप से गुमनाम रूप से हर किसी का अधिकार है, मैं हमेशा सीखने के अवसर के रूप में एक टिप्पणी की सराहना करता हूं।
alain

2
यह अब तक का सबसे आसान उत्तर / तर्क है, जिसे समझने के लिए आई.एम.ओ. ले / जोड़ / घटाव बाइनरी में केवल निम्न बिट्स से उच्च बिट्स (दाएं से बाएं) में प्रचारित होता है, दशमलव में समान। IDK क्यों कोई इसे कम करेगा।
पीटर कॉर्ड्स

1
@ बाथशीबा: CHAR_BIT की आवश्यकता नहीं है। 8. लेकिन C और C ++ में अहस्ताक्षरित प्रकारों को कुछ बिट चौड़ाई के सामान्य आधार 2 बाइनरी पूर्णांक के रूप में व्यवहार करने की आवश्यकता होती है। मुझे लगता है कि आवश्यकता है कि UINT_MAX है 2^N-1। (N को CHAR_BIT के एक बहु होने की भी आवश्यकता नहीं हो सकती है, मैं भूल जाता हूं, लेकिन मुझे पूरा यकीन है कि मानक को आवश्यकता होती है कि रैपराउंड 2 की कुछ शक्ति को मापता है।) मुझे लगता है कि आप जिस तरह से विचित्रता प्राप्त कर सकते हैं वह केवल पदोन्नति के माध्यम से है हस्ताक्षरित प्रकार जो कि सभी मामलों में धारण करने के लिए पर्याप्त चौड़ा हो aया bपर्याप्त चौड़ा न हो a+b
पीटर कोर्ड्स

2
@ बाथशीबा: हाँ, सौभाग्य से सी-एज़-पोर्टेबल-असेंबली-भाषा वास्तव में ज्यादातर अहस्ताक्षरित प्रकारों के लिए काम करती है। एक जानबूझकर शत्रुतापूर्ण सी कार्यान्वयन भी इसे तोड़ नहीं सकता है। यह केवल हस्ताक्षरित प्रकार है जहां सी में सही मायने में पोर्टेबल बिट-हैक्स के लिए चीजें भयानक हैं, और डेथस्टेशन 9000 वास्तव में आपके कोड को तोड़ सकता है।
पीटर कॉर्डेस

14

आपके पास पहले से ही स्मार्ट जवाब है: अहस्ताक्षरित अंकगणित modulo अंकगणित है और इसलिए परिणाम पकड़ लेंगे, आप इसे गणितीय रूप से साबित कर सकते हैं ...


कंप्यूटर के बारे में एक अच्छी बात यह है कि कंप्यूटर तेज हैं। वास्तव में, वे इतने तेज़ होते हैं कि 32 बिट्स के सभी वैध संयोजनों की गणना उचित मात्रा में संभव है (64 बिट्स के साथ प्रयास न करें)।

इसलिए, आपके मामले में, मैं व्यक्तिगत रूप से इसे कंप्यूटर पर फेंकना चाहता हूं; मुझे खुद को यह समझाने में कम समय लगता है कि गणितीय प्रमाण सही होने की तुलना में यह कार्यक्रम अपने आप को समझाने के लिए सही है और यह कि मैंने विनिर्देश 1 में एक विवरण की देखरेख नहीं की है :

#include <iostream>
#include <limits>

int main() {
    std::uint64_t const MAX = std::uint64_t(1) << 32;
    for (std::uint64_t i = 0; i < MAX; ++i) {
        for (std::uint64_t j = 0; j < MAX; ++j) {
            std::uint32_t const a = static_cast<std::uint32_t>(i);
            std::uint32_t const b = static_cast<std::uint32_t>(j);

            auto const champion = (a + (b & 255)) & 255;
            auto const challenger = (a + b) & 255;

            if (champion == challenger) { continue; }

            std::cout << "a: " << a << ", b: " << b << ", champion: " << champion << ", challenger: " << challenger << "\n";
            return 1;
        }
    }

    std::cout << "Equality holds\n";
    return 0;
}

के सभी संभव मूल्यों के माध्यम से यह विश्लेषण करता है aऔर bऔर 32-बिट अंतरिक्ष में चेक समानता रखती है, या नहीं। यदि ऐसा नहीं होता है, तो यह उस मामले को प्रिंट करता है जो काम नहीं करता था, जिसे आप एक स्वच्छता जांच के रूप में उपयोग कर सकते हैं।

और, क्लैंग के अनुसार : समानता रखती है

इसके अलावा, यह देखते हुए कि अंकगणित के नियम बिट-चौड़ाई के अज्ञेयवादी ( intबिट-चौड़ाई से ऊपर ) हैं, यह समानता 64 बिट्स और 128 बिट्स सहित 32 बिट्स या अधिक के किसी भी अहस्ताक्षरित पूर्णांक प्रकार के लिए धारण करेगी।

नोट: कंपाइलर उचित समय सीमा में सभी 64-बिट पैटर्न को कैसे समाहित कर सकता है? यह नहीं कर सकते। छोरों को बाहर अनुकूलित किया गया था। अन्यथा निष्पादन समाप्त होने से पहले हम सभी की मृत्यु हो जाती।


मैंने शुरुआत में इसे केवल 16-बिट्स अहस्ताक्षरित पूर्णांक के लिए सिद्ध किया था; दुर्भाग्यवश C ++ एक पागल भाषा है, जहाँ छोटे पूर्णांक (छोटे बिटवेट से int) पहले परिवर्तित हो जाते हैं int

#include <iostream>

int main() {
    unsigned const MAX = 65536;
    for (unsigned i = 0; i < MAX; ++i) {
        for (unsigned j = 0; j < MAX; ++j) {
            std::uint16_t const a = static_cast<std::uint16_t>(i);
            std::uint16_t const b = static_cast<std::uint16_t>(j);

            auto const champion = (a + (b & 255)) & 255;
            auto const challenger = (a + b) & 255;

            if (champion == challenger) { continue; }

            std::cout << "a: " << a << ", b: " << b << ", champion: "
                      << champion << ", challenger: " << challenger << "\n";
            return 1;
        }
    }

    std::cout << "Equality holds\n";
    return 0;
}

और एक बार फिर, क्लैंग के अनुसार : समानता रखती है

अच्छा, वहाँ तुम जाओ :)


1 बेशक, अगर कोई कार्यक्रम अनजाने में व्यवहार को अनजाने में ट्रिगर करता है, तो यह ज्यादा साबित नहीं होगा।


1
आप कहते हैं कि 32-बिट मानों के साथ करना आसान है लेकिन वास्तव में 16-बिट का उपयोग करें ...:
विली मेंजेल

1
@WilliMentzel: यह एक दिलचस्प टिप्पणी है। मैं शुरू में कहना चाहता था कि अगर यह 16 बिट्स के साथ काम करता है तो यह 32 बिट्स, 64 बिट्स और 128 बिट्स के साथ काम करेगा क्योंकि स्टैंडर्ड में अलग-अलग बिट-चौड़ाई के लिए विशिष्ट व्यवहार नहीं होता है ... हालाँकि मुझे याद था कि यह वास्तव में करता है की तुलना में छोटी-चौड़ाई के लिए int: छोटे पूर्णांक पहले int(एक अजीब नियम) में परिवर्तित हो जाते हैं । इसलिए मुझे वास्तव में 32-बिट्स के साथ प्रदर्शन करना है (और बाद में यह 64 बिट्स, 128 बिट्स, ...) तक फैला हुआ है।
मैथ्यू एम।

2
चूँकि आप सभी का मूल्यांकन नहीं कर सकते (4294967296 - 1) * (4294967296 - 1) संभावित परिणाम, आप किसी तरह कम करते हैं? मेरी राय MAX होनी चाहिए (4294967296 - 1) यदि आप इस तरह से चलते हैं लेकिन यह हमारे जीवनकाल के भीतर कभी भी समाप्त नहीं होगा जैसा कि आपने कहा ... तो, आखिरकार हम एक प्रयोग में समानता नहीं दिखा सकते हैं, कम से कम आप जैसे लोगों में नहीं वर्णन करते हैं।
विली मेंजेल

1
एक 2 के पूरक कार्यान्वयन पर यह परीक्षण यह साबित नहीं करता है कि साइन-मैग्नेटिट के लिए पोर्टेबल है या डेथस्टेशन 9000 प्रकार की चौड़ाई के साथ एक-पूरक है। एक संकीर्ण अहस्ताक्षरित प्रकार 17-बिट को बढ़ावा दे सकता है intजो हर संभव का प्रतिनिधित्व कर सकता है uint16_t, लेकिन a+bअतिप्रवाह कहां हो सकता है। यह केवल अहस्ताक्षरित प्रकार की तुलना में संकरी समस्या है int; C के लिए आवश्यक है कि unsignedप्रकार बाइनरी पूर्णांक हों, इसलिए रैपराउंड 2 की एक शक्ति modulo होता है
पीटर कॉर्डेस

1
C अपने स्वयं के अच्छे के लिए बहुत पोर्टेबल होने के बारे में सहमत है। यह वास्तव में अच्छा होगा जब वे 2 के पूरक, अंकगणित पर हस्ताक्षर के लिए सही बदलाव, और अपरिवर्तित-व्यवहार के शब्दार्थ के बजाय शब्दार्थ को लपेटने के साथ हस्ताक्षरित अंकगणित करने का एक तरीका होगा, जब आप लपेटना चाहते हैं । तब C एक बार फिर एक पोर्टेबल असेंबलर के रूप में उपयोगी हो सकता है, एक आधुनिक क्षेत्र अनुकूलन कंपाइलर्स की बदौलत, जो किसी भी अपरिभाषित व्यवहार को छोड़ने के लिए असुरक्षित है (कम से कम आपके लक्षित प्लेटफ़ॉर्म के लिए)। इशारा करना)।
पीटर कॉर्ड्स

4

त्वरित उत्तर है: दोनों अभिव्यक्तियाँ समकक्ष हैं

  • चूंकि aऔर b32-बिट अहस्ताक्षरित पूर्णांक हैं, परिणाम अतिप्रवाह के मामले में भी समान है। अहस्ताक्षरित अंकगणित इसकी गारंटी देता है: एक परिणाम जिसके परिणामस्वरूप अहस्ताक्षरित पूर्णांक प्रकार का प्रतिनिधित्व नहीं किया जा सकता है, उस संख्या को कम कर दिया जाता है जो उस सबसे बड़े मूल्य से अधिक है जिसे परिणामी प्रकार द्वारा दर्शाया जा सकता है।

इसका लंबा उत्तर है: ऐसे कोई भी ज्ञात प्लेटफ़ॉर्म नहीं हैं जहाँ ये अभिव्यक्तियाँ भिन्न होती हैं, लेकिन अभिन्न प्रचार के नियमों के कारण, मानक इसकी गारंटी नहीं देते हैं।

  • यदि aऔर b(अहस्ताक्षरित 32 बिट पूर्णांक) के प्रकार की तुलना में उच्च रैंक है int, तो गणना को अहस्ताक्षरित के रूप में निष्पादित किया जाता है, modulo 2 32 , और यह सभी मानों के लिए aऔर दोनों भावों के लिए समान परिभाषित परिणाम देता है b

  • इसके विपरीत, यदि का प्रकार aऔर bसे छोटा है int, तो दोनों को बढ़ावा दिया जाता है intऔर हस्ताक्षरित अंकगणित का उपयोग करके गणना की जाती है, जहां अतिप्रवाह अपरिभाषित व्यवहार को आमंत्रित करता है।

    • यदि intकम से कम 33 मान बिट्स हैं, तो उपरोक्त अभिव्यक्तियों में से कोई भी ओवरफ्लो नहीं हो सकता है, इसलिए परिणाम पूरी तरह से परिभाषित है और दोनों अभिव्यक्तियों के लिए समान मूल्य है।

    • यदि intवास्तव में 32 मान बिट्स हैं, तो गणना दोनों अभिव्यक्तियों के लिए अतिप्रवाह कर सकती है , उदाहरण के लिए मान और दोनों अभिव्यक्तियों में अतिप्रवाह होगा। इससे बचने के लिए, आपको लिखना होगा ।a=0xFFFFFFFFb=1((a & 255) + (b & 255)) & 255

  • अच्छी खबर यह है कि ऐसे कोई प्लेटफार्म 1 नहीं हैं


1 अधिक सटीक रूप से, ऐसा कोई वास्तविक मंच मौजूद नहीं है, लेकिन कोई भी इस तरह के व्यवहार को प्रदर्शित करने के लिए DS9K को कॉन्फ़िगर कर सकता है और अभी भी C मानक के अनुरूप है।


3
आपके 2 उप-भाग की आवश्यकता है (1) aसे छोटा है int(2) intमें 32 मान बिट्स (3) हैं a=0xFFFFFFFF। वे सब सच नहीं हो सकते।
बैरी

1
@ बैरी: आवश्यकताओं को पूरा करने वाला एक मामला 33-बिट है int, जहां 32 मान बिट्स और एक साइन बिट हैं।
बेन वोइगट

2

समान कोई अतिप्रवाह संभालने । न तो संस्करण वास्तव में अतिप्रवाह के लिए प्रतिरक्षा है, लेकिन डबल और संस्करण इसके लिए अधिक प्रतिरोधी है। मुझे ऐसी प्रणाली के बारे में पता नहीं है, जहां इस मामले में एक अतिप्रवाह एक समस्या है, लेकिन मैं लेखक को ऐसा करते हुए देख सकता हूं कि कोई एक है।


1
ओपी निर्दिष्ट: (ए और बी 32-बिट अहस्ताक्षरित पूर्णांक हैं) । जब तक int33 बिट्स चौड़ा नहीं होता है, तब तक परिणाम अतिप्रवाह के मामले में भी समान होता है । अहस्ताक्षरित अंकगणित इसकी गारंटी देता है: एक परिणाम जिसके परिणामस्वरूप अहस्ताक्षरित पूर्णांक प्रकार का प्रतिनिधित्व नहीं किया जा सकता है, उस संख्या को कम कर दिया जाता है जो उस सबसे बड़े मूल्य से अधिक है जिसे परिणामी प्रकार द्वारा दर्शाया जा सकता है।
चकरली

2

हाँ, आप इसे अंकगणित के साथ साबित कर सकते हैं, लेकिन अधिक सहज उत्तर है।

जब जोड़ते हैं, तो हर बिट केवल उन से अधिक महत्वपूर्ण को प्रभावित करता है; उन कम महत्वपूर्ण नहीं है।

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


0

प्रमाण तुच्छ है और पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाता है

लेकिन वास्तव में इसे एक उत्तर के रूप में वैध बनाने के लिए, आपकी पहली पंक्ति में कहा गया है कि अंतिम 8 बिट्स b** (सभी उच्चतर सेट्स bको शून्य पर ले जाएं) और इसे जोड़ें aऔर फिर परिणाम के अंतिम 8 बिट्स को सभी उच्चतर सेट करें बिट्स को शून्य।

दूसरी पंक्ति कहती है कि सभी 8 बिट्स के साथ अंतिम 8 बिट्स जोड़ें aऔर bलें।

परिणाम में केवल अंतिम 8 बिट महत्वपूर्ण हैं। इसलिए केवल पिछले 8 बिट्स इनपुट (एस) में महत्वपूर्ण हैं।

** अंतिम 8 बिट्स = 8 एलएसबी

यह भी ध्यान रखना दिलचस्प है कि आउटपुट के बराबर होगा

char a = something;
char b = something;
return (unsigned int)(a + b);

जैसा कि ऊपर, केवल 8 एलएसबी महत्वपूर्ण हैं, लेकिन परिणाम unsigned intअन्य सभी बिट्स शून्य के साथ है। a + bअतिप्रवाह जाएगा, अपेक्षित परिणाम का निर्माण किया।


नहीं यह नहीं होगा। चार गणित के रूप में होता है इंट और चार पर हस्ताक्षर किए जा सकते हैं।
अंती हापला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.