Haskell:从二进制文件中读取[Double]

时间:2015-01-13 16:26:04

标签: haskell binary

我有一个包含二进制数据的文件(更准确地说,它是一个npy文件=头数据+原始二进制数据)。这个数据(测试的[0.1,0.2,0.3,0.4])可以用C ++中的代码成功读取(跳过):

int word_size = 8;
double *data;
arr = new char[size*word_size];
size_t nread = fread(arr, word_size, size, file);
if(nread != size)
    *data = reinterpret_cast<double *>(arr);

我试图在Haskell中实现这个:

data Header = Header {
    {- other fields -}
    npyData         :: [Double]
    } deriving (Show)

getNpyData = do
    empty <- isEmpty
    if empty
        then return []
        else do 
            v <- getWord64be
            rest <- getNpyData
            return (fromIntegral v : rest)

npyHeader :: Get Header
npyHeader = do
    {-other fields -}
    npyData <- getNpyData
    return Header {
        {- other fields -}
        npyData=npyData
    }


main = do
    file <- openBinaryFile "test.npy" ReadMode
    input <- BL.hGetContents file
    let npyParsedData = runGet npyHeader input
    print $ npyData npyParsedData

这给了npyData不正确的结果(其他变量没问题):

[1.1140104038263667e19,1.114010403826367e19,3.6893488147419515e18,1.1140104038263675e19]

有人可以告诉我,这段代码有什么问题吗?

2 个答案:

答案 0 :(得分:2)

您应该尝试getFloat...(link)中的getDouble...cereal功能。

您的代码正在执行的是读取64位整数值并将其转换为Double。

答案 1 :(得分:1)

不幸的是,应该做些什么

     v <- get :: Double
由于Data.Binary没有使用IEEE754双打编码(它存储decodeFloat的结果),因此

没有。因此,一个很好的选择是使用谷物包装。至少在GHC中,我unsafeCoerce获得Word64也可以为类似的任务工作。

    bitsToDouble :: Word64 -> Double
    bitsToDouble = unsafeCoerce

可能cereal是一种更安全的方法。