2010-02-15 12 views
7

Ich möchte ein Haskell Float in einen String konvertieren, der die 32-Bit-hexadezimale Darstellung des Floats im IEEE-Standardformat enthält. Ich kann kein Paket finden, dass dies für mich tun würde. Weiß jemand von einem?Hexadezimale Darstellung von Floats in Haskell

Ich habe bemerkt, dass GHC.Float eine Funktion bietet, um einen Float in seine vorzeichenbehaftete Basis und seinen Exponenten (decodeFloat) zu zerlegen, aber dies liefert eine 14- und 8-stellige Hexadezimalzahl für die Basis bzw. den Exponenten nimmt viel mehr als 32 Bits auf. Das scheint nicht zu helfen.

Wenn es einen einfacheren Weg gibt, den ich nicht sehen kann, lass es mich wissen.

+0

Sind Floats in Haskell nur 4 Bytes (32 Bits)? Es scheint nicht genug zu sein, um Ihnen eine 14-stellige Mantisse und einen 8-Bit-Exponenten zu geben. – pavium

Antwort

4

Wie wäre es mit dem float-ieee Paket auf Hackage? http://hackage.haskell.org/package/data-binary-ieee754

Wird eine 32-Bit-IEEE754 String-Wert drucken den Schwimmer darstellt eingeleitet.

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 
+0

Dies druckt "Pi" als "@I". Ist das eine andere hexadezimale Darstellung? – Jeremy

+0

Es ist kein Hex. Es ist nur ein Bytestring. Sie benötigen eine andere Bibliothek/Funktion, um den Byte- string-Wert in Hex auszugeben. – sclv

1

Ich glaube, Sie versehentlich eine Double anstelle eines Float decodiert. Deshalb scheint es nicht zu passen.

5

Das float-ieee-Paket ist reines Haskell-98, aber sehr CPU-intensiv. Wenn Sie dies viele Male gehen zu müssen, tun, und nichts dagegen zu sein GHC spezifisch, dann verwenden Sie Code wie diesen, die extrahiert die IEEE Darstellung eines Double als 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) 

können Sie Code etwas ähnliches für Float und Word32.

+0

Technisch geht dies auch davon aus, dass "Double's in Hardware im IEEE-Format dargestellt werden, aber das ist wahrscheinlich der Fall für jede Plattform, auf der GHC läuft. Sie müssen sich auch der Endianness-Probleme bezüglich der Computerdarstellung von 'Word64' bewusst sein. –

2

Es gibt ein paar verschiedene Möglichkeiten, wie Sie es tun können, je nach Ihrem Geschmack. Mit wie Don eine Bibliothek erwähnt ist wahrscheinlich die beste Option, sonst kann man etwas entlang der Linien von ihnen versuchen:

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) 

Drei verschiedene Arten. Letzter ist GHC-spezifisch. Andere können mit anderen Haskell-Compilern zusammenarbeiten, sind aber ein wenig auf die zugrunde liegende Implementierung angewiesen, die so schwer zu garantieren ist.

Verwandte Themen