【问题标题】:Haskell converting string to binary numberHaskell将字符串转换为二进制数
【发布时间】:2018-04-28 02:42:16
【问题描述】:

我需要在 Haskell 中将一串字符转换为二进制数列表。我已经编写了两个函数来做到这一点,但我不知道如何将它们组合成一个。到目前为止我有

dec[]=[]
dec(x:xs) = ord(x): dec xs

将列表中的每个字符转换为十进制数。下一个函数

bin 0 = [0]
bin n| n `mod` 2 == 1 = bin (n `div` 2) ++ [1]
     | n `mod` 2 == 0 = bin (n `div` 2) ++ [0]

将十进制数转换为等效的二进制数。我不确定如何将第二个函数应用于列表中的每个元素,以便将每个 char 转换为其等效的二进制。我尝试使用where 子句:

where n = dec(x:xs) = ord(x): dec xs

但这是无效的,因为同一行上有两个等号。我怎样才能实现正确的功能?

【问题讨论】:

  • 你能举一个你想要的输入输出的例子(或几个例子)吗?
  • @DanielWagner 假设我给函数字符串“ab0”我希望它输出 [0,1,1,0,0,0,0,1,0,1,1,0 ,0,0,1,0,0,0,1,1,0,0,0,0]

标签: string haskell functional-programming binary


【解决方案1】:

您可以确定Int 将以二进制形式存储。它只显示为十进制,因为它在打印时转换为十进制。因此,名称dec 是用词不当,该函数将String 转换为代表每个字符的Unicode 值的数字序列。您可以通过使用 map 来避免显式递归:

toUnicode :: String -> [Int]
toUnicode = map ord

请注意,此函数使用所谓的无点样式。缺少预期的参数,但会在调用者提供时传递给 map

Bin 函数将无法编译,因为它以大写字符开头,使其成为数据构造函数。您应该以小写字符开头的函数命名。根据您的示例输出,您希望二进制表示中的前导零,因此当值变为零时您无法停止转换。您需要继续,直到您转换了所需的位数,这似乎是 8。继续追加到列表也是低效的。最好预先添加,然后反转结果。

toBinary :: Int -> [Int]
toBinary = go 8 [] where
    go 0 acc _ = reverse acc
    go n acc x = go (n-1) (bit:acc) x' where
        (x', bit) = x `divMod` 2

在这里,我们使用了一个辅助函数 go,它在构建 1 和 0 的列表时对剩余位数进行倒计时。

所以,现在我们有一个将String 转换为Ints 列表的函数,以及一个将Int 转换为0/1 Ints 列表的函数,我们想要将它们粘合在一起以创建一个将String 转换为0/1 Ints 列表的函数。如果我们 map 我们的 toBinary 函数覆盖 toUnicode 的结果,我们将得到一个列表列表,必须将它们连接起来形成一个列表。这是一种常见的模式,有一个函数可以调用,concatMap

stringToBinary :: String -> [Int]
stringToBinary = concatMap toBinary . toUnicode

这里我们使用函数组合首先将toUnicode 应用到String,然后将concatMap 应用到toBinary 上。

【讨论】:

  • 请注意,如果您包含任何 Unicode 值大于 255 的字符,则二进制表示的高位将被省略。
【解决方案2】:

我们想要的是String -> String (decimal -> binary) 类型的函数。你现在拥有的是

dec :: String -> [Int]
bin :: Int -> [Int] -- use *lowercase*

所以似乎不可能只用这两个来组合String -> String 类型的函数。而且ord不是你想要的。

*Main> dec "123"
[49,50,51]
*Main> bin 123
[0,1,1,1,1,0,1,1]

根据您现在的情况,可能的解决方案是:

*Main Data.Char> toBinary = map intToDigit . bin . read
*Main Data.Char> toBinary "123"
"01111011"

我猜你的意图可能是dec :: String -> Int,然后是bin . dec :: String -> [Int]。您可以按照类型签名并重试。

【讨论】:

    猜你喜欢
    • 2021-02-24
    • 2010-10-16
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多