Haskell에서 정수 리터럴을 바이너리 또는 16 진수로 인쇄하는 방법은 무엇입니까?
Haskell에서 정수 리터럴을 바이너리 또는 16 진수로 인쇄하는 방법은 무엇입니까?
printBinary 5 => "0101"
printHex 5 => "05"
이를 허용하는 라이브러리 / 함수는 무엇입니까?
Numeric 모듈과 showIntAtBase 함수를 발견했지만 올바르게 사용할 수 없습니다.
> :t showIntAtBase
showIntAtBase :: (Integral a) => a -> (Int -> Char) -> a -> String -> String
숫자 모듈은 여러 포함 일체형를 나타내는 함수 , 각종 기지 포함한 showIntAtBase. 다음은 몇 가지 사용 예입니다.
import Numeric (showHex, showIntAtBase)
import Data.Char (intToDigit)
putStrLn $ showHex 12 "" -- prints "c"
putStrLn $ showIntAtBase 2 intToDigit 12 "" -- prints "1100"
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
산출:
16 진수로 65535의 값은 다음과 같습니다. 0x0000ffff
html 색상 코드는 다음과 같습니다. # 00FFFF
바이너리로 된 65535의 값은 다음과 같습니다. 1111111111111111
Numeric및 Data.Char모듈 을 가져 오면 다음을 수행 할 수 있습니다.
showIntAtBase 2 intToDigit 10 "" => "1010"
showIntAtBase 16 intToDigit 1023 "" => "3ff"
이것이 작동하는 모든 것이기 때문에 16까지의 모든 염기에서 intToDigit작동합니다. 위의 예에서 빈 문자열 인수가 추가 된 이유 는 표시 표현을 기존 문자열에 연결하는 showIntAtBase유형의 함수 를 반환하기 때문 ShowS입니다.
다음과 같이 정수를 이진수로 변환 할 수 있습니다.
decToBin x = reverse $ decToBin' x
where
decToBin' 0 = []
decToBin' y = let (a,b) = quotRem y 2 in [b] ++ decToBin' a
GHCi에서의 사용법 :
Prelude> decToBin 10
[1,0,1,0]
16 진수는 다음 0x과 같이 0b접두사를 사용 하여 바이너리 로 작성할 수 있습니다 .
> 0xff
255
>:set -XBinaryLiterals
> 0b11
3
바이너리에는 BinaryLiterals확장자 가 필요합니다 .
다음과 같이 고유 한 재귀 함수를 정의 할 수 있습니다.
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
Explanation: As you can see, the toNum function converts a k-based value to decimal, using the given base and a mapping function. The mapping function will map special characters to a decimal value (for ex. A=10, B=11, ... in hex). For binary mapping you could also use a lambda expression like you see in binToDec.
Whereas the toKBaseVal function is the opposite, converting a decimal to a k-based value. Again we need a mapping function which does the opposite: from a decimal to the corresponding special character of the k-based value.
As a test you can type:
binToDec(decToBin 7) = 7
Suppose you want to convert from decimal to octal:
-- decimal to octal
decToOct :: Int -> String
decToOct x = toKBaseNum x 8 (\x -> intToDigit(x))
Again, I use just a lambda expression, because the mapping is simple: just int to digit.
Hope that helps! Good programming!
Silly solution for one-liner fans:
(\d -> let fix f = let {x = f x} in x in fmap (\n -> "0123456789abcdef" !! n) (fix (\f l n -> if n == 0 then l :: [Int] else let (q, r) = quotRem n 16 in f (r:l) q) [] d)) 247
The nucleus of the one-liner is:
quotRem 247 16
For the sake of clarity, you can, alternatively, put the following in a file:
#!/usr/bin/env stack
{- stack script --resolver lts-12.1 -}
-- file: DecToHex.hs
module Main where
import System.Environment
fix :: (a -> a) -> a
fix f = let {x = f x} in x
ff :: ([Int] -> Int -> [Int]) -> [Int] -> Int -> [Int]
ff = \f l n ->
if n == 0
then l
else
let (q, r) = quotRem n 16
in f (r:l) q
decToHex :: Int -> String
decToHex d =
fmap (\n -> "0123456789abcdef" !! n)
(fix ff [] d)
main :: IO ()
main =
getArgs >>=
putStrLn . show . decToHex . read . head
And execute the script with:
stack runghc -- DecToHex.hs 247
I used fixed-point operator just so it is an example with fixed-point operator; also because it allowed me to construct the one-liner strictly bottom-up. (Note: bottom-up development is to be discouraged.)
References: stack script syntax, Command line arguments, fix operator definition.
recursion haskell hex haskell-stack
Here is a simple, efficient, base-agnostic, Unlicenced implementation:
convertToBase :: Word8 -> Integer -> String
convertToBase b n
| n < 0 = '-' : convertToBase b (-n)
| n < fromIntegral b = [(['0'..'9'] ++ ['A' .. 'Z']) !! fromIntegral n]
| otherwise = let (d, m) = n `divMod` fromIntegral b in convertToBase b d ++ convertToBase b m
You have to import Data.Word to use Word8 (which limits the values as much as reasonably possible), and you will often need fromIntegral (if only automatic type conversions were a thing...).
'IT Share you' 카테고리의 다른 글
| C 전처리기를 사용하여 파일이 있는지 확인할 수 있습니까? (0) | 2020.11.29 |
|---|---|
| System.InvalidOperationException : 임시 클래스를 생성 할 수 없습니다 (result = 1). (0) | 2020.11.29 |
| 특정 파일에 대해 ReSharper를 비활성화하는 방법이 있습니까? (0) | 2020.11.29 |
| Oracle JDK 64 비트를 사용하는 Ubuntu 13.04에서 Eclipse Indigo가 충돌하는 이유는 무엇입니까? (0) | 2020.11.29 |
| Xcode 5에서 앱의 번들 식별자를 변경하는 방법은 무엇입니까? (0) | 2020.11.29 |