2010-02-15 19 views
7

voglio convertire un Haskell Float in una stringa che contiene la rappresentazione esadecimale a 32 bit del galleggiante in formato standard IEEE. Non riesco a trovare un pacchetto che farà questo per me. Qualcuno ne conosce uno?la rappresentazione esadecimale dei Carri in Haskell

Ho notato che GHC.Float offre una funzione per decomporre un Float nella sua base ed esponente firmati (decodeFloat), ma questo fornisce un numero esadecimale di 14 e 8 cifre rispettivamente per la base e l'esponente, che occupa molto più di 32 bit. Questo non sembra essere d'aiuto.

Se c'è un modo più semplice per farlo che non vedo, per favore fatemelo sapere.

+0

I float sono in Haskell solo 4 byte (32 bit)? Non sembra abbastanza per darti una mantissa a 14 cifre e un esponente a 8 bit. – pavium

risposta

4

E il pacchetto float-ieee su Hackage? http://hackage.haskell.org/package/data-binary-ieee754

stamperà un valore stringa IEEE754 32 bit che rappresenta il galleggiante passata.

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

Stampa "Pi" come "@I". Si tratta di una rappresentazione esadecimale diversa? – Jeremy

+0

Non è esadecimale. È solo un test. Hai bisogno di una libreria/funzione diversa per stampare il valore in maiuscolo in esadecimale. – sclv

1

Penso accidentalmente decodificato Double invece di un Float. Ecco perché non sembra adattarsi.

5

Il pacchetto float-ieee è Haskell-98 puro, ma molto intenso per la CPU. Se avete intenzione di bisogno di fare questo molte volte, e non dispiace essere GHC specifica, quindi si utilizza il codice come questo, che estrae la rappresentazione di un IEEE Double come 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) 

è possibile codificare qualcosa di simile per Float e Word32.

+0

Tecnicamente, ciò presuppone anche che i 'Double' siano rappresentati nell'hardware in formato IEEE, ma probabilmente è il caso di ogni piattaforma su cui gira GHC. Dovrai anche essere a conoscenza dei problemi di endianness relativi alla rappresentazione della macchina di 'Word64'. –

2

Ci sono diversi modi per farlo, a seconda dei gusti. Utilizzando una libreria come Don citato è probabilmente l'opzione migliore, in caso contrario si può provare qualcosa sulla falsariga di questi:

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) 

tre modi diversi. L'ultimo è specifico per GHC. Altri due potrebbero funzionare con altri compilatori Haskell, ma si basano un po 'sull'implementazione sottostante così difficile da garantire.

Problemi correlati