2015-11-18 8 views
5

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

मैं एक एल्गोरिदम लिखने की कोशिश कर रहा हूं जो सकारात्मक मानों का योग भी प्रदान करेगा जो दिए गए मान से अधिक नहीं है। मैंने कोड लिखने का प्रयास किया है हालांकि मुझे सी स्टैक ओवरफ़्लो त्रुटि मिल रही है।

sumint :: Int -> Int 
sumint x 
    | x==0 = 0 
    | x==1 = 1 
    | (x `mod` 2 == 0) && (x >= 2) = x + (sumint x-2) 
    | (x `mod` 2 /= 0) && (x >= 1) = x + (sumint x-1) 

मैं कहां से यह त्रुटि मिलना गलत जा रहा हूँ:

यहाँ मेरी कोड है?

उत्तर

12

प्रारंभिक त्रुटि: अनंत recursion

अपने कोड के माध्यम से कदम:

sumint :: Int -> Int 

अरे, एक प्रकार हस्ताक्षर। आपने धमाल मचाया।

sumint x 
    | x==0 = 0 

एक बेस केस, ठंडा।

| x==1 = 1 

एक पूरी तरह से अनावश्यक मामला। ठीक है, यकीन है ... को छोड़कर। 1 भी नहीं है तो हम इसे योग में क्यों शामिल कर रहे हैं? यह शून्य होना चाहिए (या पूरी तरह से हटा दिया जाना चाहिए)।

| (x `mod` 2 == 0) && (x >= 2) = x + (sumint x-2) 

इस मुद्दे का मांस यहां है। 1. एक्स भी महान है। 2. एक्स सकारात्मक है, हाँ। परिणाम x + (sumint x) - 2 नहीं है!

  • त्रुटि 1: नोटिस फ़ंक्शन एप्लिकेशन ऑपरेटरों की तुलना में बाघ को बांधता है, इसलिए यह x + sumint (x-2) होना चाहिए।

यह आपके स्टैक ओवरफ़्लो का कारण है। sumint 2 == 2 + (sumint 2) - 2 + (sumint 2) -2 + (sumint 2) -2 + ..., याय अनंत रिकर्सन।

| (x `mod` 2 /= 0) && (x >= 1) = x + (sumint x-1) 

एक और मामला ... विषम ... सकारात्मक ... लेकिन हम एक्स में क्यों जुड़ रहे हैं? आप बाधाओं को जोड़ना चाहते हैं, बाधाओं को नहीं। तो एक ही समय में ऊपर समस्या दूर करने की हम पाते हैं:

  • त्रुटि 2: यदि आप निर्धारित x अजीब है, x में शामिल न करें। बस sumint (x-1) का उपयोग करें।

फिर आप मामलों से बाहर हैं। क्या होता है यदि एक्स सकारात्मक नहीं है? आपको (दूसरा) मामला चाहिए।

| otherwise = 0 

अगला समस्या: कोई संचय

समस्या अब आप एक बड़े thunk (unevaluated गणना) का निर्माण कर रहे हैं के बजाय परिणाम आप प्रगति के रूप में अर्जित होने के कारण निरंतर अंतरिक्ष में सक्रिय है। सूचना है कि अगर हम के लिए कहते हैं, अपने गणना का विस्तार, 6 हम पाते हैं:

sumint 6 = 6 + sumint (6-2) 
     = 6 + 4 + sumint (4-2) 
     = 6 + 4 + 2 + sumint (2-2) 
     = 6 + 4 + 2 + 0 

आप वास्तव में नहीं है उन सभी अतिरिक्त अलग रखने के लिए, चाहते हैं कि उसे इस तरह के रूप में एक संचायक में पारित करने के लिए अच्छा होगा:

sumint x = go x 0 
where 
    go n accumulator 
     | n <= 0 = accumulator 
     | odd n  = go (n-1) accumulator 
     | otherwise = go (n-2) (accumulator + n) 

साइड नोट: अन्य स्टैक ओवरफ्लो नागरिक संचयक को सख्त बनाने का उल्लेख कर सकते हैं, जो कि अच्छा रूप है। मैं वर्तमान चर्चाकर्ता को उस चर्चा के साथ विचलित नहीं करना चाहता हूं। अनुकूलन का उपयोग कर नोटिस, -O2, पर्याप्त है।

मुहावरेदार समाधान

उपरोक्त सभी समाधान नहीं बल्कि अत्यधिक शब्द हैं। सामान्य ऑपरेशन, फ़ंक्शन और संचयक के साथ एक सूची में पुनरावृत्त, fold का एक प्रकार है। मोड़ कार्यात्मक प्रोग्रामिंग में आम तौर पर कई अत्यधिक अनुकूलित संरचना ट्रैवर्सल में से एक है। इस मामले में एक "सख्त बाएं गुना" सामान्य उम्मीदवार है (Data.List से)। l का मतलब है कि l का मतलब है कि foldl' 'प्राइम (') का मतलब है कि यह सख्त है।

sumint n = foldl' (+) 0 [val | val <- [0..n], even val] 

यहां हमने अपनी राशि प्राप्त करने के लिए सूची में तब्दील किया। ब्याज की सूची बनाने के लिए हमने सूची समझ का उपयोग किया - पहले 0..n से मूल्यों की गणना करना और किसी भी मान को छोड़ना जो even को पूर्ववत नहीं करता है।

हम आगे इस को साफ और sum समारोह और सूची समझ है कि 2 से कदम, इस प्रकार हमें केवल evens आप इच्छा देने का उपयोग करके इसे सुधार कर सकते हैं:

sumint n = sum [0,2..n] 
+0

ग्रेट, धन्यवाद। वास्तव में मुझे क्या चाहिए। –

+0

छोटे विवरण: 'go'' को 'sumint'' की परिभाषा में '(+)' के साथ प्रतिस्थापित किया जाना चाहिए जो 'foldl'' का उपयोग करता है। मैं यह संपादन कर दूंगा लेकिन परिवर्तन 6 वर्णों से कम है। – liminalisht

10

इसकी एक ऑपरेटर प्राथमिकता समस्या है। हास्केल में, फ़ंक्शन एप्लिकेशन में उच्चतम संभव प्राथमिकता होती है। इस प्रकार जब आप sumint x - 2 लिखते हैं, भले ही आप इसे sumint (x-2) के रूप में व्याख्या कर रहे हों, हास्केल इसे (sumint x) - 2 के रूप में व्याख्या कर रहा है। इस प्रकार - आप सीधे sumint xsumint x के संदर्भ में परिभाषित करने की कोशिश कर रहे हैं - जो स्टैक ओवरफ्लो तक रिकर्सिव फ़ंक्शन कॉल को ढेर करता है। यदि आप फंक्शन एप्लिकेशन से पहले घटाव मूल्यांकन करना चाहते हैं तो आपको स्पष्ट कोष्ठक जोड़ने की आवश्यकता है।

+0

ठीक के लिए धन्यवाद! –

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