解决
我的功能不正常。当我做hex2dec" 100"或" 10000"它给了我16而不是正确的256.当我做hex2dec" 101"它给了我17而不是正确的257.
hex2dec :: String -> Integer
hex2dec str = go (reverse str)
where go [] = 0
go (x:xs) = hexChar x + 16 * hex2dec xs
hexChar :: Char -> Integer
hexChar c
| c == '0' = 0
| c == '1' = 1
| c == '2' = 2
| c == '3' = 3
| c == '4' = 4
| c == '5' = 5
| c == '6' = 6
| c == '7' = 7
| c == '8' = 8
| c == '9' = 9
| c == 'a' = 10
| c == 'b' = 11
| c == 'c' = 12
| c == 'd' = 13
| c == 'e' = 14
| c == 'f' = 15
| otherwise = 0
答案 0 :(得分:2)
我不得不改变" hex2dec"去"去"。
hex2dec :: String -> Integer
hex2dec str = go (reverse str)
where go [] = 0
go (x:xs) = hexChar x + 16 * go xs
答案 1 :(得分:0)
请注意,您的功能是不完整的;并非所有Char
值都是有效的十六进制数字。相反,定义一个新类型来表示它们:
data Hex = H0 | H1 | H2 | H3
| H4 | H5 | H6 | H7
| H8 | H9 | HA | HB
| HC | HD | HE | HF deriving (Enum)
导出Enum
个实例会为您提供hexChar
(让我们称之为hexInt
)几乎免费;我们在这里从Int
切换到Integer
。
hexInt :: Hex -> Integer
hexInt = fromIntegral . fromEnum
有了这个,您可以使用Horner的规则将Hex
值列表缩减为Integer
。
hex2dec :: [Hex] -> Integer
hex2dec = foldr (\d acc -> hexInt d + 16*acc) 0
要从[Hex]
到String
进行概括,我们首先定义一个将Char
转换为Maybe Hex
import Data.List
charToHex :: Char -> Maybe Hex
charToHex c = fmap toEnum $ c `elemIndex` "0123456789abcdef"
-- elemIndex returns a Maybe Int "between" Just 0 and Just 15;
-- fmap toEnum converts that to a Maybe Hex.
如果你想要明确,charToHex
当然只是
charToHex '0' = Just H0
-- ...
charToHex 'f' = Just H15
charToHex _ = Nothing
然后我们想要一个能够在charToHex
上映射String
时处理任何失败的函数。
str2dec :: String -> Maybe Integer
str2dec = fmap hex2dec . traverse charToHex
如果对输入字符串的traverse charToHex :: String -> Maybe [Hex]
的任何调用返回Nothing
,则charToHex
返回Nothing
。