2016-10-20 12 views
7

मुझे कोड का यह स्निपेट मिला जो काम करता है, लेकिन मुझे समझ में नहीं आता कि यह क्यों करता है। यह एक इंट को बाइनरी में इसके प्रतिनिधित्व में परिवर्तित करता है।हास्केल में दशमलव से दशमलव तक कनवर्ट करना

repBinario::Int -> Int 
repBinario 0 = 0 
repBinario x = 10 * repBinario (x `div` 2) + x `mod` 2 

मुझे पता है कि div और mod है। हालांकि, यह mod से प्रत्येक नंबर को कैसे रखता है?

+2

मुझे प्रश्न समझ में नहीं आता है। – melpomene

+0

@melpomene मैं जानना चाहता था कि हर बार 'रिपबिनारियो' कहलाता था, यह रिकर्सन मेरे जैसे नौसिखिया के लिए थोड़ा उलझन में था। नीचे दिए गए उत्तरों हालांकि हम वास्तव में उपयोगी हैं। – Tepes

+0

उत्तर हम बहुत उपयोगी हैं, मैंने केवल एक ही नहीं चुना क्योंकि कुछ लोग शायद वही चीज़ ढूंढ रहे हों जो मैं था, वैसे भी, मैंने प्रत्येक उत्तर को ऊपर उठाने का फैसला किया क्योंकि उनमें से सभी ने समस्या को अलग तरीके से संरचित किया था और तो सवाल के परिणामस्वरूप विविधीकृत समाधान, सभी समान रूप से दिलचस्प। धन्यवाद। – Tepes

उत्तर

6

संक्षेप में, यह प्रत्येक पुनरावृत्ति पर संचित परिणाम 10 द्वारा गुणा करता है।

क्या हो रहा है इसकी स्पष्ट समझ प्राप्त करने के लिए हम आपके कार्य को दो सरल में विभाजित कर सकते हैं। पहला एक पूर्णांक को बाइनरी अंकों की सूची में परिवर्तित करेगा। दूसरा तो वही काम करेगा जो आपको परेशान करता है: एक पूर्णांक में बाइनरी अंकों की एक सूची को सम्मिलित करें।

extractBinDigits :: Int -> [Int] 
extractBinDigits = 
    unfoldr (\x -> if x == 0 then Nothing else Just (mod x 2, div x 2)) 

concatDigits :: [Int] -> Int 
concatDigits = 
    foldr (\a b -> a + b * 10) 0 

जैसा कि आप देख हम केवल हर कदम पर 10 द्वारा संचायक गुणा और इसे करने के लिए प्रत्येक अंक जोड़ने सूची गुना।

फिर अपने मूल कार्य हो जाता है तो बस इस:

repBinario :: Int -> Int 
repBinario = 
    concatDigits . extractBinDigits 

डिवीजन अब हमें निरीक्षण और अधिक से अधिक लचीलेपन के साथ हमें उपलब्ध कराना हमारे कार्यक्रम के महीन टुकड़े का पुन: उपयोग करने देता है। उदाहरण के लिए, एक और सरल समारोह जोड़कर आप अब पूर्णांक एक स्ट्रिंग में बदल सकते हैं एक ही बार में:

showDigits :: [Int] -> String 
showDigits = 
    reverse . map (chr . (+ 48)) 

repStringyBinario :: Int -> String 
repStringyBinario = 
    showDigits . extractBinDigits 
5

एक उदाहरण के माध्यम से जाना है, तो दो:

repBinario 5 

repBinario 5 के स्थानापन्न परिभाषा:

10 * repBinario (5 `div` 2) + 5 `mod` 2 

कम div और mod:

10 * repBinario 2 + 1 
        ^

यहां हमने अपना पहला अंक बनाया है, ^ के साथ चिह्नित है।repBinario 2 की

स्थानापन्न परिभाषा:

10 * (10 * repBinario (2 `div` 2) + 2 `mod` 2) + 1 
               ^

कम div और mod:

repBinario 1 की
10 * (10 * repBinario 1 + 0) + 1 
         ^^

स्थानापन्न परिभाषा:

10 * (10 * (10 * repBinario (1 `div` 2) + 1 `mod` 2) + 0) + 1 
                ^^

कम div और mod:

10 * (10 * (10 * repBinario 0 + 1) + 0) + 1 
           ^^^

स्थानापन्न repBinario 0 की परिभाषा:

10 * (10 * (10 * 0 + 1) + 0) + 1 
        ^^^

कम करें:

101 

हर कदम पर, (`mod` 2) कम से कम महत्वपूर्ण बाइनरी अंक हो जाता है, और (`div` 2) संख्या दाहिनी ओर बदलाव , अंक को छोड़कर और शेष संख्या को पुनः प्राप्त करने के लिए टी ओ divBinario। अंत में, हम विपरीत प्रक्रिया करते हैं: (+ d) परिणाम के लिए वर्तमान अंक जोड़ता है, और (* 10) संख्या बाईं ओर स्थानांतरित करता है ताकि हम और अधिक अंक जोड़ सकें।

आपको जो दशमलव मिलता है वह दशमलव संख्या है जो मूल इनपुट के बाइनरी प्रतिनिधित्व के समान दिखता है।

आप 10 द्वारा गुणा निकालते हैं, तो आप popCount, एक समारोह है कि आप की आबादी गिनती देता मिलता है एक नंबर-अपनी द्विआधारी प्रतिनिधित्व में 1 बिट्स की संख्या:

popCount 0 = 0 
popCount x = popCount (x `div` 2) + x `mod` 2 

popCount 5 == 2 
5

मैं इसे लगता है हाथ से एक छोटे से मूल्य के लिए इस समारोह की गणना करना सबसे अच्छा होगा - यह संभव है क्योंकि यह एक शुद्ध कार्य है इसलिए आप बाएं हाथ की तरफ अपनी परिभाषा (यानी दाएं हाथ की ओर) के साथ प्रतिस्थापित कर सकते हैं - इस सुविधा के लिए फैंसी कंप्यूटर विज्ञान शब्द " संदर्भित पारदर्शिता "।

repBinario 24 = 10 * repBinario (24 `div` 2) + 24 `mod` 2 
       = 10 * repBinario 12 + 0 
       = 10 * (10 * repBinario (12 `div` 2) + 12 `mod` 2) 
       = 100 * repBinario 6 + 0 
       = 100 * (10 * repBinario (6 `div` 2) + 6 `mod` 2) 
       = 1000 * repBinario 3 + 0 
       = 1000 * (10 * repBinario (3 `div` 2) + 3 `mod` 2) 
       = 10000 * repBinario 1 + 1000 * 1 
       = 10000 (10 * repBinario (1 `div` 2) + 1 `mod` 2) + 1000 
       = 10000 (10 * repBinario 0 + 1) + 1000 
       = 10000 (10 * 0 + 1) + 1000 
       = 10000 * 1 + 1000 
       = 11000 
उन कदमों में

मैं सिर्फ अपनी परिभाषा के द्वारा समारोह का मूल्यांकन किया और तथ्य यह है कि पूर्णांक अलावा/गुणा वितरण के कानून का पालन करते थे।

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