将二进制转换为十进制Haskell

时间:2018-01-25 08:09:43

标签: haskell functional-programming binary

我需要一个程序,我输入一个二进制系统编号,并以十进制数字给我返回相同的数字。

binToDec :: Integer -> Integer

binToDec 1110101011111111000000111100001010101011110010000001 = 4134096010394753

binToDec 111111111111111111111111111111111111111111111111111111111111111 =  9223372036854775807 

我还需要在不到5秒的时间内编译上面的例子。

我设法做到了这一点,但问题是它是从整数列表开始的:

binToDec l = sum $ map (2^) $ findIndices (==1) $ reverse l

1 个答案:

答案 0 :(得分:3)

给出"十进制" number只包含0和1,我们可以使用 recursion

bintodec :: Integral i => i -> i
bintodec 0 = 0
bintodec i = 2 * bintodec (div i 10) + (mod i 10)

所以我们在这里所做的就是使用div i 10来"将第一个转移到右边"。我们使用递归并与 two 相乘以使用二进制表示。我们还使用mod i 10来获取我们随后添加到数字的最后一位数字。

如上所述,这不是很安全,因为例如它也会为bintodec 10010202010生成一个数字,在这种情况下我们可以返回Maybe i

bintodec :: Integral i => i -> Maybe i
bintodec 0 = Just 0
bintodec i | last < 2 = fmap (\x -> 2*x + last) (bintodec (div i 10))
           | otherwise = Nothing
    where last = mod i 10

然后产生:

Prelude> bintodec 1110101011111111000000111100001010101011110010000001
Just 4134096010394753
Prelude> bintodec 11101010111111110000001111000010101014011110010000001
Nothing

例如,使用[Bool]会更好,因为这会强制我们无法提供不是有效位串的值。在这种情况下,我们可以使用:

bintodec :: [Bool] -> Int
bintodec = foldr (\x y -> fromEnum x + 2*y) 0