क्या यह कार्यक्रम हर इंटेगर के लिए समाप्त होगा?


14

गेट तैयारी के लिए एक आंशिक परीक्षा में एक सवाल था:

f(n):
     if n is even: f(n) = n/2
     else f(n) = f(f(n-1))

मैंने उत्तर दिया "यह सभी पूर्णांक के लिए समाप्त हो जाएगा", क्योंकि कुछ नकारात्मक पूर्णांकों के लिए भी, यह स्टैक ओवरफ्लो त्रुटि के रूप में समाप्त होगा ।

लेकिन मेरे मित्र ने यह कहते हुए असहमति जताई कि चूंकि यह कोड और सिर्फ छद्म कोड लागू नहीं है, इसलिए यह कुछ नकारात्मक पूर्णांकों के मामले में अनंत पुनरावृत्ति होगा।

कौन सा उत्तर सही है और क्यों?


8
यह n = -1 के लिए समाप्त नहीं हुआ है। ज्यादातर सैद्धांतिक सीमाएं ऐसे मामलों में मानी जाती हैं।
दीप जोशी

9
यदि स्टैक ओवरफ्लो को समाप्ति के रूप में माना जाता है, तो सभी कार्यक्रम समाप्त हो जाएंगे और यह इस प्रश्न के उद्देश्य को हरा देता है ...
xuq01

10
@ xuq01 while (true);न तो समाप्त होगा और न ही किसी भी समझदारी पर, स्टैक ओवरफ्लो का कारण होगा।
ट्रिपहाउंड

3
@leftaroundabout मैं शायद "का इस्तेमाल किया है नहीं करना चाहिए कुछ भी समझदार पर " क्योंकि इसके बारे में एक पूरी तरह से अलग स्तर है " समझदार " ... खोलना और पूंछ प्रत्यावर्तन को लागू है अच्छा (या यहां तक कि समझदार ), लेकिन ऐसा न करने केवल थोड़ा "है समझदार नहीं "। कुछ भी जो while(true);एक तरह से लागू होता है जो किसी भी स्टैक का उपयोग करता है वह निश्चित रूप से समझदार नहीं होगा । बिंदु यह है, जब तक कि आप जानबूझकर अपने रास्ते से बाहर नहीं निकल गए हैं, तब तक while(true);न तो समाप्त होगा और न ही स्टैक ओवरफ्लो को ट्रिगर करेगा।
ट्रिपहाउंड

14
@ xuq01 मुझे नहीं लगता कि "ब्रह्मांड का विनाश" रुकने की समस्या के समाधान के रूप में गिना जाता है।
ट्रिपहाउंड

जवाबों:


49

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

यहां तक ​​कि अगर यह एक वास्तविक प्रोग्रामिंग भाषा थी, तब भी सही उत्तर "समाप्त नहीं होता है", जब तक कि स्टैक का उपयोग भाषा की परिभाषा का हिस्सा न हो। अधिकांश भाषाएं उन कार्यक्रमों के व्यवहार को निर्दिष्ट नहीं करती हैं जो स्टैक को ओवरफ्लो कर सकते हैं, क्योंकि यह जानना मुश्किल है कि प्रोग्राम कितने स्टैक का उपयोग करेगा।

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

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


3
एक उदाहरण जहाँ कोडिंग प्रोग्रामिंग भाषा में अनुवादित कोड के परिणामस्वरूप कोई स्टैक ओवरफ़्लो नहीं होता है। यह बस अनिश्चित काल तक let f :: Int -> Int; f n = if even n then n `div` 2 else f (f (n - 1)) in f (-1)
चलता है

5

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

f(n):
   if n is even: f(n) = n/2
   else f(n) = f(f(n-1))

साथ में

f(n):
   if n is even: f(n) = n/2
   else f(n) = f((n-1) / 2)

अब पूंछ पुनरावृत्ति लागू करने के लिए कार्यान्वयन की अनुमति है:

f(n):
   while n is not even do n = (n-1) / 2
   f(n) = n/2

और यह हमेशा के लिए बंद हो जाता है अगर और केवल अगर n = -1।


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