2010-02-15 11 views
7

Quiero convertir un flotador Haskell en una cadena que contiene la representación hexadecimal de 32 bits del flotador en formato IEEE estándar. Parece que no puedo encontrar un paquete que haga esto por mí. ¿Alguien sabe de uno?Representación hexagonal de flotadores en Haskell

He notado que GHC.Float ofrece una función para descomponer un Float en su base y exponente firmado (decodeFloat), pero esto proporciona un número hexadecimal de 14 y 8 dígitos para la base y el exponente, respectivamente, que ocupa mucho más de 32 bits. Esto no parece ayudar.

Si hay una manera más fácil de hacer esto que no estoy viendo, por favor avíseme.

+0

¿Los flotadores en Haskell solo son de 4 bytes (32 bits)? No parece suficiente para darte una mantisa de 14 dígitos y un exponente de 8 bits. – pavium

Respuesta

4

¿Qué tal el paquete float-ieee en Hackage? http://hackage.haskell.org/package/data-binary-ieee754

imprimirá un valor de cadena IEEE754 32 bits que representa el flotador en el pasado.

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

Esto imprime "Pi" como "@I". ¿Es esta una representación hexagonal diferente? – Jeremy

+0

No es hexadecimal. Es solo una cadena de bytes. Necesita una biblioteca/función diferente para imprimir el valor de la cadena de bytes en hexadecimal. – sclv

1

Creo que accidentalmente se descifró un Double en lugar de un Float. Es por eso que no parece encajar.

5

El paquete float-ieee es puro Haskell-98, pero requiere mucha CPU. Si va a tener que hacer esto muchas veces, y no le importa ser GHC específica, a continuación, utiliza un código como éste, que extrae la representación IEEE de un Double como 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) 

Puede codificar algo similar para Float y Word32.

+0

Técnicamente, esto también asume que 'Double's están representados en hardware en formato IEEE, pero ese es probablemente el caso para cada plataforma en la que se ejecuta GHC. También deberá tener en cuenta los problemas de endianness con respecto a la representación de máquina de 'Word64'. –

2

Existen diferentes maneras de hacerlo, dependiendo de su gusto. El uso de una biblioteca como Don mencionado es probablemente la mejor opción, de lo contrario se puede intentar algo en la línea de éstos:

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) 

tres maneras diferentes. El último es específico de GHC. Otros dos pueden funcionar con otros compiladores de Haskell, pero confían un poco en la implementación subyacente, tan difícil de garantizar.

Cuestiones relacionadas