[英]Haskell converting string to binary number
I need to convert a string of chars to a list of binary numbers in Haskell. 我需要将一个字符串转换为Haskell中的二进制数列表。 I've written two functions to do this, but I'm not sure how to combine them into one.
我已经编写了两个函数来执行此操作,但是我不确定如何将它们组合为一个。 So far I have
到目前为止,我有
dec[]=[]
dec(x:xs) = ord(x): dec xs
to convert every char in the list into a decimal number. 将列表中的每个字符转换为十进制数。 The next function
下一个功能
bin 0 = [0]
bin n| n `mod` 2 == 1 = bin (n `div` 2) ++ [1]
| n `mod` 2 == 0 = bin (n `div` 2) ++ [0]
converts a decimal number to its binary equivalent. 将十进制数转换为其等效的二进制数。 I'm not sure how to apply the second function to every element in the list, in order to convert every char to its equivalent in binary.
我不确定如何将第二个函数应用于列表中的每个元素,以便将每个字符转换为等效的二进制值。 I tried to use the
where
clause: 我尝试使用
where
子句:
where n = dec(x:xs) = ord(x): dec xs
but this is not valid as there are two equals signs on the same line. 但这是无效的,因为同一行上有两个等号。 How can I achieve the correct functionality?
如何获得正确的功能?
You can be pretty certain that an Int
will be stored in binary. 您可以确定一个
Int
将以二进制形式存储。 It only appears to be in decimal because it is converted to decimal when you print it. 它仅显示为十进制,因为在打印时会转换为十进制。 So, the name
dec
is a misnomer, that function is converting a String
into a sequence of numbers that represent the Unicode value of each character. 因此,名称
dec
是用词不当,该函数将String
转换为代表每个字符的Unicode值的数字序列。 You can avoid explicit recursion by using map: 您可以使用map避免显式递归:
toUnicode :: String -> [Int]
toUnicode = map ord
Note that this function uses so-called point-free style. 请注意,此函数使用所谓的无点样式。 The expected argument is missing, but will be passed to
map
when supplied by the caller. 预期的参数丢失,但是在调用方提供时将传递给
map
。
The Bin
function will not compile because it starts with an upper case character, making it a data constructor. Bin
函数不会编译,因为它以大写字母开头,使其成为数据构造函数。 You should name the function starting with a lower case character. 您应以小写字母开头的函数命名。 According to your example output, you want leading zeros in your binary representations, so you can't stop conversion when the value becomes zero.
根据示例输出,您希望二进制表示形式中的前导零,因此当值变为零时就不能停止转换。 You need to continue until you have converted the desired number of digits, which appears to be 8. It is also inefficient to keep appending to a list.
您需要继续操作,直到转换了所需的数字位数(看来是8)为止。保持附加到列表的效率也很低。 It is better to prepend, and then reverse the result.
最好先添加,然后反转结果。
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
Here, we use a helper function, go
which counts down the number of remaining digits as it builds up the list of 1's and 0's. 在这里,我们使用一个辅助函数
go
,它在建立1和0的列表时对剩余位数进行计数。
So, now we have a function to convert a String
into a list of Int
s, and a function to convert an Int
into a list of 0/1 Int
s, and we want to glue them together to make a function that converts a String
to a list of 0/1 Int
s. 因此,现在我们有了一个将
String
转换为Int
列表的函数,以及一个将Int
转换为0/1 Int
列表的函数,并且我们希望将它们粘合在一起以构成一个将String
转换为函数的函数。到0/1 Int
列表。 If we map
our toBinary
function over the result of toUnicode
, we will get a list of lists, which must be concatenated to form a single list. 如果
map
toBinary
函数map
到toUnicode
的结果上,则会得到一个列表列表,该列表必须串联起来形成一个列表。 This is such a common pattern that there's a function for that called, concatMap
: 这是一种常见的模式,因此有一个名为
concatMap
的函数:
stringToBinary :: String -> [Int]
stringToBinary = concatMap toBinary . toUnicode
Here we use function composition to first apply toUnicode
to the String
, and then concatMap
the toBinary
over the result. 在这里,我们使用函数组合首先将
toUnicode
应用于String
,然后对结果进行concatMap
toBinary
。
What we want is a function of type String -> String
( decimal -> binary
). 我们想要的是一个类型为
String -> String
( decimal -> binary
)的函数。 What you have now is 您现在拥有的是
dec :: String -> [Int]
bin :: Int -> [Int] -- use *lowercase*
So it seems impossible to compose a function of type String -> String
only with these two. 因此,似乎不可能仅用这两个组成String-
String -> String
类型的函数。 Besides, ord
is not what you want. 此外,
ord
不是您想要的。
*Main> dec "123"
[49,50,51]
*Main> bin 123
[0,1,1,1,1,0,1,1]
From what you have now, the possible solution would be: 从现在开始,可能的解决方案是:
*Main Data.Char> toBinary = map intToDigit . bin . read
*Main Data.Char> toBinary "123"
"01111011"
I guess your intention may be dec :: String -> Int
, then bin . dec :: String -> [Int]
我想您的意图可能是
dec :: String -> Int
,然后是bin . dec :: String -> [Int]
bin . dec :: String -> [Int]
. bin . dec :: String -> [Int]
You can follow the type signature and retry. 您可以遵循类型签名并重试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.