このコードスニペットはうまくいきましたが、それはなぜわかりません。これは、Intをバイナリ表現に変換します。HaskellでDecimalをBinaryに変換する
repBinario::Int -> Int
repBinario 0 = 0
repBinario x = 10 * repBinario (x `div` 2) + x `mod` 2
私は何をすべきかdiv
とmod
知っています。しかし、mod
から来る各番号はどのように配置されますか?
このコードスニペットはうまくいきましたが、それはなぜわかりません。これは、Intをバイナリ表現に変換します。HaskellでDecimalをBinaryに変換する
repBinario::Int -> Int
repBinario 0 = 0
repBinario x = 10 * repBinario (x `div` 2) + x `mod` 2
私は何をすべきかdiv
とmod
知っています。しかし、mod
から来る各番号はどのように配置されますか?
要するに、累積結果に各繰り返しで10
を乗算します。
何が起こっているのかをより明確に理解するために、関数を2つの簡単な関数に分けることができます。最初のものは、整数をバイナリ数字のリストに変換します。もう一方はあなたを悩ますことを正確に行います:バイナリ数字のリストを整数に連結します。
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
だが、その後、例えば、見ていきましょう:例えば、別の簡単な関数を追加することによって、あなたが今一度に文字列に整数に変換することができ
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
との削減:repBinario 0
の
10 * (10 * (10 * repBinario 0 + 1) + 0) + 1
^^^
代替定義:
10 * (10 * (10 * 0 + 1) + 0) + 1
^^^
削減:各ステップ
101
を(`mod` 2)
が最下位のバイナリ桁を取得し、(`div` 2)
が右数をシフト、数字を破棄して残りの数字を再帰的に渡すt o divBinario
。最後に、逆の処理を行います。(+ d)
は現在の桁を結果に加算し、(* 10)
は数字を左ににシフトし、桁数を増やすことができます。
あなたが得るのは、がの元の入力と同じに見える10進数です。
あなたは10
乗算を削除する場合は、popCount
、あなたの人口数を与える関数を得る数のバイナリ表現で1
ビット数:私はそれを考える
popCount 0 = 0
popCount x = popCount (x `div` 2) + x `mod` 2
popCount 5 == 2
この関数を手で小さな値で計算するのが最善でしょう。これは純粋な関数なので、可能です。左辺をその定義(つまり右辺)に置き換えることができます。この機能の幻想的なコンピュータサイエンスワードは、参照透明度 "と定義する。これらのステップで
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
私はちょうどその定義によって機能を評価し、整数加算/乗算は、分布の法則に従うという事実を使用していました。
質問が分かりません。 – melpomene
@melpomene私は 'repBinario'が呼び出されるたびに何が起こったのか知りたかったので、この再帰は私のような初心者のためにちょっと混乱しました。以下の答えは本当に便利です。 – Tepes
私たちは非常に役に立ちました。私は同じものを探していない人もいたので、私はただ一つしか選んでいませんでした。その質問は多様な解決策をもたらし、すべて同じように興味深いものでした。ありがとうございました。 – Tepes