2014-10-27 10 views
9

एक परीक्षा के लिए समीक्षा करते समय मैंने देखा कि मैंने एक तार्किक त्रुटि लिखी है और मेरा मानना ​​है कि यह यौगिक असाइनमेंट + के कारण है क्योंकि वृद्धि ++ इरादे के रूप में निष्पादित होती है लेकिन यह तब होती है जब foo +1 को foo के मान को निर्दिष्ट किया जाता है याएक लूप परिणाम में foo + = foo + 1 क्यों होता है -1?

foo += foo + 1; 

यहां कोड है।

//Break Statement 
    Boolean exit = false; 
    int foo = 1, bar = 60; 
    while (!exit) {   
     foo+=foo+1; //Bad Code 
     //foo++; //Good Code 
     //foo=foo+1; // Good Code 
     //foo+=1; // Good Code 
     //System.out.println(foo); //Results in -1 (Infinite Loop) 
     if (foo == bar) { 
      break; 
     } 
     System.out.println("stuff"); 
    } 

मेरा प्रश्न है कि foo + = foo + 1 परिणाम -1 में क्यों होता है?

कृपया ध्यान दें: मैं स्टैक ओवरफ्लो में नया हूं और आपके उत्तर को वोट देने में असमर्थ हूं इसलिए पता है कि मैं किसी भी मदद के लिए आभारी हूं और अग्रिम धन्यवाद!

+2

आप उत्तर के बगल में स्थित चेकमार्क पर क्लिक करके एक उत्तर स्वीकार कर सकते हैं। –

+0

मैं नहीं देखता कि इसका परिणाम '-1'' होगा। यह पहली पुनरावृत्ति पर 3 होना चाहिए। यह एक अनंत लूप हो सकता है क्योंकि यह 60 वें नंबर पर सही होगा। लेकिन यह कहकर तय किया जा सकता है कि 'if (foo> = bar) ' –

+1

मैं इस प्रश्न में आपके कोड के साथ इसे पुन: उत्पन्न नहीं कर सकता। क्या आप समस्या को कुछ प्रतिलिपि बनाने के लिए नीचे निकाल सकते हैं? अक्सर आप पाएंगे कि यह प्रक्रिया पहले से ही आपके प्रश्न का उत्तर देगी। –

उत्तर

13

यदि आप लूप के अंत में -1 होने के बारे में बात कर रहे हैं; ऐसा इसलिए है क्योंकि int पर हस्ताक्षर है और यह चारों ओर लपेटता है।

int foo = 1; 
while (foo >= 0) { 
    foo += foo + 1; 
} 
System.out.println(foo); 

output -1 होगा। आप trace through it:

foo += 1 + 1 ---> 3 
foo += 3 + 1 ---> 7 
foo += 7 + 1 ---> 15 
foo += 15 + 1 ---> 31 
foo += 31 + 1 ---> 63 
foo += 63 + 1 ---> 127 
foo += 127 + 1 ---> 255 
foo += 255 + 1 ---> 511 
foo += 511 + 1 ---> 1023 
foo += 1023 + 1 ---> 2047 
foo += 2047 + 1 ---> 4095 
foo += 4095 + 1 ---> 8191 
foo += 8191 + 1 ---> 16383 
foo += 16383 + 1 ---> 32767 
foo += 32767 + 1 ---> 65535 
foo += 65535 + 1 ---> 131071 
foo += 131071 + 1 ---> 262143 
foo += 262143 + 1 ---> 524287 
foo += 524287 + 1 ---> 1048575 
foo += 1048575 + 1 ---> 2097151 
foo += 2097151 + 1 ---> 4194303 
foo += 4194303 + 1 ---> 8388607 
foo += 8388607 + 1 ---> 16777215 
foo += 16777215 + 1 ---> 33554431 
foo += 33554431 + 1 ---> 67108863 
foo += 67108863 + 1 ---> 134217727 
foo += 134217727 + 1 ---> 268435455 
foo += 268435455 + 1 ---> 536870911 
foo += 536870911 + 1 ---> 1073741823 
foo += 1073741823 + 1 ---> 2147483647 
foo += 2147483647 + 1 ---> -1 

गणित बस उस तरह से काम करता है। प्रत्येक पुनरावृत्ति का परिणाम उस मान में होता है जो 2 की शक्ति से कम 1 होता है। मुझे लगता है कि अगर आपने बीजगणित का काम किया है तो आप इसे दिखा सकते हैं। तो यह समझ में आता है कि यह -1 हिट करेगा, जो 32-बिट पर int पर हस्ताक्षर किए गए हैं, 2 -1 है।

फिर tom और Tomáš Zíma स्पष्ट रूप से इंगित करते हैं, यह अटक जाता है क्योंकि -1 + -1 + 1 अभी भी -1 है।

यह भी ध्यान दें, जैसा कि नीचे दी गई टिप्पणियों में टॉम की खोज की गई है, कि आप -1 हिट करेंगे, इससे कोई फर्क नहीं पड़ता कि आप किस नंबर से शुरुआत करते हैं। ऐसा इसलिए है क्योंकि foo += foo + 1foo = 2 * foo + 1 जैसा ही है, जो वास्तव में केवल foo = (foo << 1) | 1 है (बाएं शिफ्ट [परिणाम कम 0 में परिणाम] फिर कम बिट चालू करें - संख्या को जोड़ने के बाद 1 जोड़कर)। इससे कोई फर्क नहीं पड़ता कि आप किस 32 से शुरू करते हैं (या फिर कई बिट्स हैं) पुनरावृत्तियों के बाद, अंत में आप बाईं तरफ से अपने शुरुआती मूल्य को सभी तरह से स्थानांतरित कर देंगे और इसे सभी 1 के साथ बदल देंगे (जो, दो पूरक में हस्ताक्षरित int, मान -1 है)। जैसे एक हस्ताक्षरित 8 बिट संख्या के साथ:

abcdefgh   starting foo, 8 unknown bits 
bcdefgh0   add to itself (or multiply by two, or left shift) 
bcdefgh1   add one 
... 
cdefgh11   again 
defgh111   and again 
efgh1111   and again 
fgh11111   and again 
gh111111   and again 
h1111111   and again 
11111111   and again, now it's -1 
... and for completeness: 
11111110   left shift -1 
11111111   add 1, it's back to -1 

संयोग से, कोई बात नहीं क्या नंबर पर आप के साथ शुरू, आप कभी नहीं मारा जाएगा 60 (या किसी भी सम संख्या, उस बात के लिए)।आप इसे कुछ त्वरित बीजगणित के साथ दिखा सकते हैं: यदि 60 = 2 * foo + 1, तो पिछले foo = 59/2 जो पहले से ही पूर्णांक नहीं है; तो आपके पास कभी भी पूर्णांक नहीं होगा foo जैसे 60 = 2 * foo + 1

+0

से बहुत कुछ सीखा है यह मुझे कुछ सिखाया। धन्यवाद। – tom

+1

यदि आप इसे 2 (या किसी अन्य नंबर) पर शुरू करते हैं, तो भी आप -1 दबाते हैं। Weird.http: //ideone.com/jQIzb6 – tom

+0

@tom वाह। वह * थोड़ी अजीब है। मुझे अपने वेब ब्राउजर को बंद करने की ज़रूरत है, इसलिए मैं यह समझने की कोशिश नहीं कर रहा हूं कि इस पर गणित के साथ बिल्ली क्या चल रहा है ... 8-) –

7
foo += foo + 1 

रूप

foo = (foo) + (foo + 1) 

नहीं foo = (foo + 1)

पार्स किया गया है आप

1: 3 (+ 1 + 2) 
2: 7 (+3 + 4) 
3: 15 (+7 +8) 
4: 31 (+15 +16) 
5: 63 (+32 +33) 

मिल अर्थ आदि

तो तुमकभी नहीं करेंगेऔर इसके बजाय एक अनंत लूप।

ईटा: ऐसा लगता है कि मैंने अभी कुछ खुद सीखा है। Int रोल और हिट -1। धन्यवाद @Jason C

+0

चूंकि foo कभी बराबर बार नहीं हो सकता है, यह संभवतः एक अतिप्रवाह त्रुटि हो सकता है? मैंने कभी अंकगणितीय अनुक्रम परिणाम का अनुभव नहीं किया है -1। –

+0

एक स्टैक ओवरफ़्लो स्टैक स्पेस से बाहर निकलने का परिणाम होगा, जो आमतौर पर तब होता है जब रिकर्सिव फ़ंक्शन कॉल बहुत गहरी हो जाती है। ओपी के कोड में कुछ भी नहीं है जो स्टैक स्पेस का उपभोग करता है। –

+0

आप सही हैं। और एक बार यह -1 हिट हो जाता है, यह वहां रहता है। – tom

3

निम्नलिखित कोड पर विचार करें:

public class Test { 
    public static void main(String[] args) { 
     int foo = 1; 
     while (true) { 
      foo += foo + 1; 
      System.out.println(foo); 
     } 
    } 
} 

कुछ पुनरावृत्तियों के बाद, यह बार बार -1 प्रिंट करता है। यहां क्यों है: अतिप्रवाह! जैसे ही foo का मान 2147483647 के बराबर है, परिणाम -1 होगा। मूल्यांकन की जा रही अभिव्यक्ति इस तरह दिखती है:

2147483647 + 2147483647 + 1 // which is -1, given you work with int 

एक बार जब आप -1 प्राप्त कर लेंगे, तो यह कभी भी मूल्य को कभी नहीं बदलेगा। क्यूं कर?

foo += foo + 1 

मूल रूप से, बराबर

foo = foo + foo + 1 

जो है, foo = -1 के साथ के रूप में ही है:

foo = -1 + -1 + 1 

कारण अपने पाश कभी नहीं समाप्त होता है हालत में है आप उपयोग किया गया। फू कभी 60 के बराबर नहीं होगा। और यही बात है।

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