【问题标题】:Convert Binary to Decimal Haskell将二进制转换为十进制 Haskell
【发布时间】:2018-01-25 20:16:30
【问题描述】:

我需要一个程序,我可以在其中输入一个二进制系统数字,然后以十进制为基数将相同的数字返回给我。

binToDec :: Integer -> Integer

binToDec 1110101011111111000000111100001010101011110010000001 = 4134096010394753

binToDec 111111111111111111111111111111111111111111111111111111111111111 =  9223372036854775807 

我还需要在 5 秒内编译完上面的示例。

我已经做到了,但问题是它从整数列表开始:

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

【问题讨论】:

  • 您不应将Integer 用于此“二进制数”。字符串输入或布尔值列表会更合适。
  • 需要在 5 秒内编译上述示例?这听起来非常可疑,就像您滥用编译器进行转换一样。不要那样做。 — 如果你真的需要在 Haskell 源代码中写出二进制文件,只需使用 -XBinaryLiterals 扩展名。

标签: haskell functional-programming binary


【解决方案1】:

鉴于“十进制”数字仅包含零和一,我们可以为此使用递归

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

【讨论】:

  • 可能没有Maybe i?
  • @mathandtic:这是该程序的第一个版本。您可以选择两者中的任何一个。但第二个更安全。
猜你喜欢
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 2016-08-28
  • 2017-07-15
相关资源
最近更新 更多