如何在haskell中以二进制或十六进制打印整数文字?

发布于 2024-08-16 05:11:14 字数 329 浏览 4 评论 0原文

如何在haskell中以二进制或十六进制打印整数文字?

printBinary 5 => "0101"

printHex 5 => "05"

哪些库/函数允许这样做?

我遇到了 Numeric 模块及其 showIntAtBase 函数,但无法正确使用它。

> :t showIntAtBase 

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

How to print integer literals in binary or hex in haskell?

printBinary 5 => "0101"

printHex 5 => "05"

Which libraries/functions allow this?

I came across the Numeric module and its showIntAtBase function but have been unable to use it correctly.

> :t showIntAtBase 

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

萌能量女王 2024-08-23 05:11:15

您还可以使用 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

You may also use printf of the printf package to format your output with c style format descriptors:

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

Output:

The value of 65535 in hex is: 0x0000ffff
The html color code would be: #00FFFF
The value of 65535 in binary is: 1111111111111111

阿楠 2024-08-23 05:11:15

如果导入 NumericData.Char 模块,您可以执行以下操作:

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

这适用于 16 以内的任何基数,因为这就是 intToDigit< /code> 适用于。上面示例中额外的空字符串参数的原因是 showIntAtBase 返回一个 ShowS 类型的函数,该函数会将显示表示形式连接到现有字符串上。

If you import the Numeric and Data.Char modules, you can do this:

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

This will work for any bases up to 16, since this is all that intToDigit works for. The reason for the extra empty string argument in the examples above is that showIntAtBase returns a function of type ShowS, which will concatenate the display representation onto an existing string.

深府石板幽径 2024-08-23 05:11:15

您可以使用如下所示将整数转换为二进制:

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]

You can convert integer to binary with something like the following:

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

usage in GHCi:

Prelude> decToBin 10
[1,0,1,0]
离去的眼神 2024-08-23 05:11:15

十六进制可以用 0x 编写,二进制可以用 0b 前缀编写,例如:

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

请注意,二进制需要 BinaryLiterals 扩展名。

Hex can be written with 0x and binary with 0b prefix e.g.:

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

Note that binary requires the BinaryLiterals extension.

掩饰不了的爱 2024-08-23 05:11:15

您可以定义自己的递归函数,例如:

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、...,十六进制)。对于二进制映射,您还可以使用 lambda 表达式,如 binToDec 中所示。

toKBaseVal 函数则相反,将小数转换为基于 k 的值。同样,我们需要一个执行相反操作的映射函数:从小数到基于 k 的值的相应特殊字符。

作为测试,您可以输入:

binToDec(decToBin 7) = 7

假设您想要从十进制转换为八进制:

-- decimal to octal
decToOct :: Int -> String
decToOct x = toKBaseNum x 8 (\x -> intToDigit(x))

同样,我只使用 lambda 表达式,因为映射很简单:只需将 int 转换为 digital。

希望有帮助!很好的编程!

You could define your own recursive functions like:

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!

最笨的告白 2024-08-23 05:11:15

对于单行爱好者来说愚蠢的解决方案:

(\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

单行的核心是:

quotRem 247 16

为了清楚起见,您也可以将以下内容放入文件中:

#!/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

并使用以下命令执行脚本:

stack runghc -- DecToHex.hs 247

我使用了定点运算符,因此它是一个定点运算符的示例;还因为它允许我严格自下而上地构建单行代码。 (注意:不鼓励自下而上的开发。)

参考:堆栈脚本语法命令行参数修复运算符定义

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.

温馨耳语 2024-08-23 05:11:15

这是一个简单、高效、与基础无关的无许可实现:

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

您必须导入 Data.Word 使用 Word8 (它尽可能合理地限制值),并且您经常需要 fromIntegral (如果只有自动类型转换的话.. .)。

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...).

抚笙 2024-08-23 05:11:15

使用 FiniteBits 类:

import Data.Bits (FiniteBits, finiteBitSize, testBit, shiftR)

showBits :: FiniteBits a => a -> String
showBits bits =
  go (finiteBitSize bits - 1) where
    go shift =
      if shift >= 0
        then
          let bit = if testBit (shiftR bits shift) 0 then '1' else '0'
          in bit : go (pred shift)
        else
          ""

示例:

showBits (4 :: Word8) => “00000100”

showBits (50::Int16) => "0000000000110010"

showBits (-127::Int32) => “11111111111111111111111110000001”

Using the FiniteBits class:

import Data.Bits (FiniteBits, finiteBitSize, testBit, shiftR)

showBits :: FiniteBits a => a -> String
showBits bits =
  go (finiteBitSize bits - 1) where
    go shift =
      if shift >= 0
        then
          let bit = if testBit (shiftR bits shift) 0 then '1' else '0'
          in bit : go (pred shift)
        else
          ""

Examples:

showBits (4 :: Word8) => "00000100"

showBits (50 :: Int16) => "0000000000110010"

showBits (-127 :: Int32) => "11111111111111111111111110000001"

别理我 2024-08-23 05:11:15

使用 text 时,我建议使用 text-show 包,其中包括:

例如,将 Integer 转换为二进制的 Text

{-# LANGUAGE OverloadedStrings #-}

import TextShow (toText)
import TextShow.Data.Integral (showbBin)

toBinary :: Integer -> Text
toBinary n = toText . showbBin

> toBinary 6 == "110"

也许您想添加 Text 前缀。 Builder允许您高效地构造Text;它是一个幺半群。

toBinaryWithPrefix :: Text -> Integer -> Text
toBinaryWithPrefix prefix n = toText $ fromText prefix <> showbBin n

有关详细信息,请参阅 TextShowTextShow.Data.Integral 模块。

When working with text, I recommend using the text-show package which includes:

For example, converting an Integer to Text in binary:

{-# LANGUAGE OverloadedStrings #-}

import TextShow (toText)
import TextShow.Data.Integral (showbBin)

toBinary :: Integer -> Text
toBinary n = toText . showbBin

> toBinary 6 == "110"

Perhaps you want to add a Text prefix. Builder allows you to efficiently construct Text; it is a monoid.

toBinaryWithPrefix :: Text -> Integer -> Text
toBinaryWithPrefix prefix n = toText $ fromText prefix <> showbBin n

For more information see the TextShow and TextShow.Data.Integral modules available on Hackage.

与之呼应 2024-08-23 05:11:14

Numeric 模块包含多个用于显示整数类型的函数在各种基础上,包括 showIntAtBase。以下是一些使用示例:

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

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

The Numeric module includes several functions for showing an Integral type at various bases, including showIntAtBase. Here are some examples of use:

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

putStrLn $ showHex 12 "" -- prints "c"
putStrLn $ showIntAtBase 2 intToDigit 12 "" -- prints "1100"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文