2009-12-24 120 views
54

如何以二進制或十六進制打印haskell中的整數文字?如何在haskell中以二進制或十六進制打印整數文字?

printBinary 5 => "0101" 

printHex 5 => "05" 

哪些庫/函數允許這樣做?

我遇到了Numeric模塊及其showIntAtBase函數,但一直無法正確使用它。

> :t showIntAtBase 

showIntAtBase :: (Integral a) => a -> (Int -> Char) -> a -> String -> String 

回答

69

數字模塊包括幾個functions for showing an Integral type在不同的基地,包括showIntAtBase。下面是使用的一些例子:

import Numeric (showHex, showIntAtBase) 
import Data.Char (intToDigit) 

putStrLn $ showHex 12 "" -- prints "c" 
putStrLn $ showIntAtBase 2 intToDigit 12 "" -- prints "1100" 
+6

對於像我這樣沒有向下滾動的懶惰的人來說,printf示例更加簡潔靈活,並且可以執行其他有用的操作,例如,給出一個恆定長度的字符串和所有其他printf功能。而不是以上,只是: 'printf「%032b」5' – mozboz 2015-06-24 11:36:08

+11

@mozboz,Haskell中的'printf'更像是一個魔術,而不是一個用在嚴肅代碼中的函數。格式字符串在運行時被解析(這可能會產生運行時錯誤),整個機制有點慢。 – dfeuer 2015-10-18 16:15:00

+0

這一個不適用於負數。 – CMCDragonkai 2017-04-04 13:04:42

3

可以轉換整數,像下面爲二進制:在GHCI

decToBin x = reverse $ decToBin' x 
    where 
    decToBin' 0 = [] 
    decToBin' y = let (a,b) = quotRem y 2 in [b] ++ decToBin' a 

用法:

Prelude> decToBin 10 
[1,0,1,0] 
+0

在最後一行的末尾有b:(decToBIn a)會不會更好? – prince 2015-12-05 15:27:13

+0

不應該0回饋0? 'decToBin'0 = [0]'也許? – Jaseem 2016-11-03 10:50:12

+0

@SjB,對負數不起作用 – 2016-11-14 15:41:56

26

如果導入NumericData.Char模塊,你可以這樣做:

showIntAtBase 2 intToDigit 10 "" => "1010" 
showIntAtBase 16 intToDigit 1023 "" => "3ff" 

這將爲任何基地多達16個工作,因爲這是所有intToDigit適用於。以上示例中額外的空字符串參數的原因是showIntAtBase返回類型爲ShowS的函數,該函數將顯示錶示連接到現有字符串。

24

您也可以使用printf的包的printf到您的輸出使用C風格的格式描述格式爲:

import Text.Printf 

main = do 

    let i = 65535 :: Int 

    putStrLn $ printf "The value of %d in hex is: 0x%08x" i i 
    putStrLn $ printf "The html color code would be: #%06X" i 
    putStrLn $ printf "The value of %d in binary is: %b" i i 

輸出:

的65535十六進制值是:0x0000ffff
的html顏色代碼將是:#00FFFF
二進制中的值65535是:1111111111111111

+0

'printf「十六進制中的%d的值是:0x%08x」我是'是好的,因爲printf可以是'IO()'和'字符串' – Nybble 2012-02-14 08:17:30

+0

是的的確的。我只是想弄明白,它可以用作返回String的純函數。 – 2012-12-10 20:20:32

4

六角可以寫與0x和二進制與0b前綴例如: -

> 0xff 
255 
>:set -XBinaryLiterals 
> 0b11 
3 

請注意二進制需要BinaryLiterals擴展。

2

你可以定義你自己喜歡的遞歸函數:

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表達式,因爲映射很簡單:只需詮釋數字。

希望有幫助!好的編程!

相關問題