8

Haskell Float を、標準 IEEE 形式の float の 32 ビット 16 進表現を含む String に変換したいと考えています。これを行うパッケージが見つからないようです。誰か知っていますか?

GHC.Float が Float を符号付きの基数と指数に分解する関数 (decodeFloat) を提供していることに気付きましたが、これは基数と指数にそれぞれ 14 桁と 8 桁の 16 進数を提供し、それはさらに多くを占めます。 32ビット以上。これは役に立たないようです。

これを行う簡単な方法があれば、私に知らせてください。

4

4 に答える 4

6

float-ieee パッケージは純粋な Haskell-98 ですが、非常に CPU を集中的に使用します。これを何度も行う必要があり、GHC 固有であることを気にしない場合は、 a の IEEE 表現をDoubleとして抽出する次のようなコードを使用します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)

Floatとについて同様のコードを作成できますWord32

于 2010-02-16T05:32:31.457 に答える
4

Hackage の float-ieee パッケージはどうですか? http://hackage.haskell.org/package/data-binary-ieee754

渡された float を表す 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
于 2010-02-16T00:21:53.587 に答える
2

好みに応じて、いくつかの方法があります。ドンが言及したようなライブラリを使用するのがおそらく最良の選択肢です。それ以外の場合は、次の行に沿って何かを試すことができます。

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)

3 つの異なる方法。最後はGHC固有です。他の 2 つは、他の Haskell コンパイラで動作する可能性がありますが、基礎となる実装に少し依存しているため、保証が困難です。

于 2010-09-21T07:33:41.533 に答える
1

Double誤って aではなくa をデコードしたと思いますFloat。そのため、合わないようです。

于 2010-02-16T00:30:45.380 に答える