Haskell 中浮点数的十六进制表示

发布于 2024-08-21 20:14:04 字数 240 浏览 5 评论 0原文

我想将 Haskell 浮点数转换为包含标准 IEEE 格式浮点数的 32 位十六进制表示形式的字符串。我似乎找不到一个可以为我完成此操作的软件包。有人知道其中一个吗?

我注意到 GHC.Float 提供了一个将 Float 分解为其有符号基数和指数的函数 (decodeFloat),但这分别为基数和指数提供了 14 位和 8 位十六进制数,这占用了更多的空间大于 32 位。这似乎没有帮助。

如果我没有看到更简单的方法,请告诉我。

I want to convert a Haskell Float to a String that contains the 32-bit hexadecimal representation of the float in standard IEEE format. I can't seem to find a package that will do this for me. Does anybody know of one?

I've noticed that GHC.Float offers a function to decompose a Float into its signed base and exponent (decodeFloat), but this provides a 14- and 8-digit hex number for the base and exponent, respectively, which takes up much more than 32 bits. This doesn't seem to help.

If there's an easier way to do this that I'm not seeing, please let me know.

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

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

发布评论

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

评论(4

懵少女 2024-08-28 20:14:05

根据您的口味,您可以采用几种不同的方法来做到这一点。使用像 Don 提到的库可能是最好的选择,否则您可以尝试以下方法:

doubleToBytes :: Double -> [Int]
doubleToBytes d
   = runST (do
        arr <- newArray_ ((0::Int),7)
        writeArray arr 0 d
        arr <- castDoubleToWord8Array arr
        i0 <- readArray arr 0
        i1 <- readArray arr 1
        i2 <- readArray arr 2
        i3 <- readArray arr 3
        i4 <- readArray arr 4
        i5 <- readArray arr 5
        i6 <- readArray arr 6
        i7 <- readArray arr 7
        return (map fromIntegral [i0,i1,i2,i3,i4,i5,i6,i7])
     )

-- | Store to array and read out individual bytes of array
dToStr :: Double -> String
dToStr d
  = let bs     = doubleToBytes d
        hex d' = case showHex d' "" of
                     []    -> error "dToStr: too few hex digits for float"
                     [x]   -> ['0',x]
                     [x,y] -> [x,y]
                     _     -> error "dToStr: too many hex digits for float"

        str  = map toUpper $ concat . fixEndian . (map hex) $ bs
    in  "0x" ++ str

-- | Create pointer to Double and cast pointer to Word64, then read out
dToStr2 :: Double -> IO String
dToStr2 f = do
    fptr <- newStablePtr f
    let pptr = castStablePtrToPtr fptr
    let wptr = (castPtrToStablePtr pptr)::(StablePtr Word64)
    w <- deRefStablePtr wptr
    let s = showHex w ""
    return ("0x" ++ (map toUpper s))

-- | Use GHC specific primitive operations
dToStr3 :: Double -> String
dToStr3 (D# f) = "0x" ++ (map toUpper $ showHex w "")
    where w = W64# (unsafeCoerce# f)

三种不同的方法。最后是 GHC 特定的。其他两个可能与其他 Haskell 编译器一起工作,但有点依赖于底层实现,因此很难保证。

There are a few different ways you can do it, depending on your taste. Using a library like Don mentioned is probably the best option, otherwise you can try something along the lines of these:

doubleToBytes :: Double -> [Int]
doubleToBytes d
   = runST (do
        arr <- newArray_ ((0::Int),7)
        writeArray arr 0 d
        arr <- castDoubleToWord8Array arr
        i0 <- readArray arr 0
        i1 <- readArray arr 1
        i2 <- readArray arr 2
        i3 <- readArray arr 3
        i4 <- readArray arr 4
        i5 <- readArray arr 5
        i6 <- readArray arr 6
        i7 <- readArray arr 7
        return (map fromIntegral [i0,i1,i2,i3,i4,i5,i6,i7])
     )

-- | Store to array and read out individual bytes of array
dToStr :: Double -> String
dToStr d
  = let bs     = doubleToBytes d
        hex d' = case showHex d' "" of
                     []    -> error "dToStr: too few hex digits for float"
                     [x]   -> ['0',x]
                     [x,y] -> [x,y]
                     _     -> error "dToStr: too many hex digits for float"

        str  = map toUpper $ concat . fixEndian . (map hex) $ bs
    in  "0x" ++ str

-- | Create pointer to Double and cast pointer to Word64, then read out
dToStr2 :: Double -> IO String
dToStr2 f = do
    fptr <- newStablePtr f
    let pptr = castStablePtrToPtr fptr
    let wptr = (castPtrToStablePtr pptr)::(StablePtr Word64)
    w <- deRefStablePtr wptr
    let s = showHex w ""
    return ("0x" ++ (map toUpper s))

-- | Use GHC specific primitive operations
dToStr3 :: Double -> String
dToStr3 (D# f) = "0x" ++ (map toUpper $ showHex w "")
    where w = W64# (unsafeCoerce# f)

Three different ways. Last is GHC specific. Other two may work with other Haskell compilers but are relying a little on the underlying implementation so hard to guarantee.

满地尘埃落定 2024-08-28 20:14:05

我认为您不小心解码了 Double 而不是 Float。这就是为什么它看起来不适合。

I think you accidentally decoded a Double instead of a Float. That's why it doesn't seem to fit.

戏舞 2024-08-28 20:14:04

float-ieee 包是纯 Haskell-98,但是 CPU 密集型。如果您需要多次执行此操作,并且不介意特定于 GHC,那么您可以使用这样的代码,它将 Double 的 IEEE 表示形式提取为 Word64< /code>:

import GHC.Prim
import GHC.Types
import GHC.Word

encodeIEEEDouble :: Double -> Word64
encodeIEEEDouble (D# x) = W64# (unsafeCoerce# x)

decodeIEEEDouble :: Word64 -> Double
decodeIEEEDouble (W64# x) = D# (unsafeCoerce# x)

您可以为 FloatWord32 编写类似的代码。

The float-ieee package is pure Haskell-98, but very CPU intensive. If you are going to need to do this many times, and don't mind being GHC specific, then you use code like this, which extracts the IEEE representation of a Double as a Word64:

import GHC.Prim
import GHC.Types
import GHC.Word

encodeIEEEDouble :: Double -> Word64
encodeIEEEDouble (D# x) = W64# (unsafeCoerce# x)

decodeIEEEDouble :: Word64 -> Double
decodeIEEEDouble (W64# x) = D# (unsafeCoerce# x)

You can code something similar for Float and Word32.

甜嗑 2024-08-28 20:14:04

Hackage 上的 float-ieee 包怎么样? http://hackage.haskell.org/package/data-binary-ieee754

将打印一个 32 位 ieee754 字符串值,表示传入的浮点数。

import Data.Binary.Put
import Data.Binary.IEEE754
import qualified Data.ByteString.Lazy.Char8 as S

main = do
    let s = runPut $ putFloat32be pi
    S.putStrLn s

How about the float-ieee package on Hackage? http://hackage.haskell.org/package/data-binary-ieee754

Will print a 32 bit ieee754 string value representing the float passed in.

import Data.Binary.Put
import Data.Binary.IEEE754
import qualified Data.ByteString.Lazy.Char8 as S

main = do
    let s = runPut $ putFloat32be pi
    S.putStrLn s
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文