如何在Haskell中实现Decimal到Binary函数

Tru*_*Tru 3 binary recursion haskell functional-programming list-comprehension

我在Haskell中实现了二进制到十进制函数,并且我正在处理一个将十进制转换为二进制值的函数.(我知道这些功能在某处可用,尽管它们不属于Prelude.hs)

我想出了一个C类过程语言的代码,但我很难将其应用到功能范例中.

while (n > 0)
{
    if (n % 2 == 1)
        str = str + "1";
    else
        str = str + "0";
    n = n / 2;
}
Run Code Online (Sandbox Code Playgroud)

我最近才冒险进入Haskell的函数式编程,所以我对功能性思维方式很陌生.我使用递归和列表推导尝试了上述内容,但我不确定如何正确放置警卫和逻辑,因为这涉及多个条件.我使用Int列表来保存单独的二进制位.

--Decimal to binary
toBin:: Int -> [Int]
toBin 0 = [0]
toBin n | (n % 2 == 1) =
        |(n % 2 == 0) = 
Run Code Online (Sandbox Code Playgroud)

我已经明白,上面的模式会让程序选择guard和end来评估函数.我在这里走错了路吗?

下面是我提出的原始递归,将任何基数(小于10,代替2)转换为十进制.

toDecimal :: [Int] -> Int
toDecimal [] = 0
toDecimal (x:xs) = (x * 2 ^(length xs)) + bin xs
Run Code Online (Sandbox Code Playgroud)

提前致谢.

ehi*_*ird 15

没有%经营者; 你可能正在寻找`mod`:

toBin 0 = [0]
toBin n | n `mod` 2 == 1 = ...
        | n `mod` 2 == 0 = ...
Run Code Online (Sandbox Code Playgroud)

Guards允许您在函数的多个分支之间进行选择.在这种情况下,每个...都是toBin n其相应条件为真的结果.要将两个列表附加在一起,您可以使用++运算符,并`div`对应于整数除法:

toBin 0 = [0]
toBin n | n `mod` 2 == 1 = toBin (n `div` 2) ++ [1]
        | n `mod` 2 == 0 = toBin (n `div` 2) ++ [0]
Run Code Online (Sandbox Code Playgroud)

但是,这有一些问题.首先,它总是以0多余的方式开始结果; 另外,使用++ [1]很慢,因为它必须通过整个列表来添加元素到最后; 这将是更好的前面加上,因为我们去的每个元素,然后扭转在最后的结果.

为了解决这两个问题,我们将分toBin为主函数和辅助函数:

toBin 0 = [0]
toBin n = reverse (helper n)

helper 0 = []
helper n | n `mod` 2 == 1 = 1 : helper (n `div` 2)
         | n `mod` 2 == 0 = 0 : helper (n `div` 2)
Run Code Online (Sandbox Code Playgroud)

在这个版本中,我们使用:运算符,它接受一个值和一个列表,并返回带有前置值的列表.我们还在助手中返回0的空结果,toBin而是处理0的情况,这样结果中不再需要0.

我们可以helper通过完全跳过警卫来简化代码,因为我们只是n `mod` 2在右侧再次写出结果:

helper 0 = []
helper n = (n `mod` 2) : helper (n `div` 2)
Run Code Online (Sandbox Code Playgroud)

最后,还有,做了一个功能divmod一气呵成,从而可以更高效:

helper 0 = []
helper n = let (q,r) = n `divMod` 2 in r : helper q
Run Code Online (Sandbox Code Playgroud)

另外要注意,这并没有真正将十进制转换为二进制,它将整数转换为二进制; Haskell实现不太可能以十进制格式存储整数,尽管它们是以该格式编写和打印的.要将十进制的完整转换写入二进制,将需要一个将十进制字符串解析为整数的函数.


mor*_*rdo 5

toBinary :: Int -> [ Int ]

toBinary 0 = [ 0 ]

toBinary n = toBinary ( n `quot` 2 ) ++ [ n `rem` 2 ]
Run Code Online (Sandbox Code Playgroud)