你可以定義你自己喜歡的遞歸函數:
import Data.Char (digitToInt)
import Data.Char (intToDigit)
-- generic function from base to decimal
toNum :: [Char] -> Int -> (Char -> Int) -> Int
toNum [] base map = 0
toNum s base map = base * toNum (init(s)) base map + map(last(s))
-- generic function from decimal to base k
toKBaseNum :: Int -> Int -> (Int -> Char) -> [Char]
toKBaseNum x base map | x < base = [map x]
| otherwise = toKBaseNum (x `div` base) base map ++ [map(x `mod` base)]
-- mapping function for hex to decimal
mapHexToDec :: Char -> Int
mapHexToDec x | x == 'A' = 10
| x == 'B' = 11
| x == 'C' = 12
| x == 'D' = 13
| x == 'E' = 14
| x == 'F' = 15
| otherwise = digitToInt(x) :: Int
-- map decimal to hex
mapDecToHex :: Int -> Char
mapDecToHex x | x < 10 = intToDigit(x)
| x == 10 = 'A'
| x == 11 = 'B'
| x == 12 = 'C'
| x == 13 = 'D'
| x == 14 = 'E'
| x == 15 = 'F'
-- hex to decimal
hexToDec :: String -> Int
hexToDec [] = 0
hexToDec s = toNum s 16 mapHexToDec
-- binary to decimal
binToDec :: String -> Int
binToDec [] = 0
binToDec s = toNum s 2 (\x -> if x == '0' then 0 else 1)
-- decimal to binary
decToBin :: Int -> String
decToBin x = toKBaseNum x 2 (\x -> if x == 1 then '1' else '0')
-- decimal to hex
decToHex :: Int -> String
decToHex x = toKBaseNum x 16 mapDecToHex
說明: 正如你所看到的,toNum功能轉換的k基於價值爲十進制,使用給定的基礎和映射函數。映射函數將特殊字符映射爲十進制值(例如,A = 10,B = 11,...,十六進制)。對於二進制映射,您也可以使用像在binToDec中看到的lambda表達式。
而toKBaseVal函數是相反的,將小數轉換爲基於k的值。我們再次需要一個映射函數,它相反:從十進制到基於k值的對應特殊字符。
作爲一個測試,你可以輸入:
binToDec(decToBin 7) = 7
假設你想從十進制轉換爲八進制:
-- decimal to octal
decToOct :: Int -> String
decToOct x = toKBaseNum x 8 (\x -> intToDigit(x))
同樣,我只使用一個lambda表達式,因爲映射很簡單:只需詮釋數字。
希望有幫助!好的編程!
對於像我這樣沒有向下滾動的懶惰的人來說,printf示例更加簡潔靈活,並且可以執行其他有用的操作,例如,給出一個恆定長度的字符串和所有其他printf功能。而不是以上,只是: 'printf「%032b」5' – mozboz 2015-06-24 11:36:08
@mozboz,Haskell中的'printf'更像是一個魔術,而不是一個用在嚴肅代碼中的函數。格式字符串在運行時被解析(這可能會產生運行時錯誤),整個機制有點慢。 – dfeuer 2015-10-18 16:15:00
這一個不適用於負數。 – CMCDragonkai 2017-04-04 13:04:42