二进制转换为十进制Haskell

oo7oh9g9  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(164)

我需要一个程序,我在其中输入一个二进制系统的数字,并返回相同的数字给我在十进制基地。

binToDec :: Integer -> Integer

binToDec 1110101011111111000000111100001010101011110010000001 = 4134096010394753

binToDec 111111111111111111111111111111111111111111111111111111111111111 =  9223372036854775807

我还需要在不到5秒的时间内编译上述示例。
我已经设法做到了这一点,但问题是它从一个整数列表开始:

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

wgeznvg71#

给定“decimal”数只包含0和1,我们可以使用 recursion 来实现:

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

所以我们在这里使用div i 10来“将数字1向右移动”。我们使用递归和乘以 * 2 * 来使用二进制表示。我们还使用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
sauutmhj

sauutmhj2#

decToBin :: Integer -> Integer
decToBin = convert' 10 2

binToDec :: Integer -> Integer
binToDec = convert' 2 10

convertAny :: Integer -> Integer -> Integer -> Integer
convertAny from to = convert' 10 to . convert' from 10

convert' :: Integer -> Integer -> Integer -> Integer
convert' from to | validBase from && validBase to = go
  where
    go 0 = 0
    go k | valid = r + from * go q
         | otherwise =
           error $ "Invalid digit (" ++ show d ++ ") for base " ++ show from
       where
         valid = d < from
         d = k `mod` 10
         (q,r) = k `divMod` to
    validBase b = b >=2 && b <= 10
convert' _ _ = error "Bases must be between 2 and 10.

相关问题