在Haskell中尝试从Hex转换为Dec时,为什么会得到错误的结果?

时间:2016-08-18 00:38:58

标签: haskell recursion

解决

我的功能不正常。当我做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

2 个答案:

答案 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