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)
最后,还有,做了一个功能div和mod一气呵成,从而可以更高效:
helper 0 = []
helper n = let (q,r) = n `divMod` 2 in r : helper q
Run Code Online (Sandbox Code Playgroud)
另外要注意,这并没有真正将十进制转换为二进制,它将整数转换为二进制; Haskell实现不太可能以十进制格式存储整数,尽管它们是以该格式编写和打印的.要将十进制的完整转换写入二进制,将需要一个将十进制字符串解析为整数的函数.
toBinary :: Int -> [ Int ]
toBinary 0 = [ 0 ]
toBinary n = toBinary ( n `quot` 2 ) ++ [ n `rem` 2 ]
Run Code Online (Sandbox Code Playgroud)