为什么在Haskell中尝试从十六进制转换为十进制时会得到错误的结果?
已解决 我的功能不能正常工作。当我执行hex2dec“100”或“10000”时,它给出的是16,而不是正确的256。当我做hex2dec“101”时,它给出的是17,而不是正确的257为什么在Haskell中尝试从十六进制转换为十进制时会得到错误的结果?,haskell,recursion,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 :: Cha
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
我不得不把“hex2dec”改成“go”
注意你的函数是局部的;并非所有的
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
有了它,您可以使用霍纳规则将Hex
值列表减少为整数
hex2dec :: [Hex] -> Integer
hex2dec = foldr (\d acc -> hexInt d + 16*acc) 0
为了将其从[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
其中transverse charToHex::String->Maybe[Hex]
返回Nothing
如果对输入字符串上的charToHex
进行任何调用都返回Nothing为了避免调用reverse
,请尝试使用累加器使用尾部递归来编写它-例如@ErikR得到了它。谢谢你的主意。hex2dec acc[]=acc hex2dec acc(x:xs)=hex2dec(acc*16+hexChar x)xsTips:查看Data.List.findIndex
,了解编写hexChar
的更好方法。如果这不是练习,还有Numeric.readHex
。谢谢。是的,这不是一个练习。只是一个代码版本的挑战。。。。那些不是练习吗?
str2dec :: String -> Maybe Integer
str2dec = fmap hex2dec . traverse charToHex