我有一个包含二进制数据的文件(更准确地说,它是一个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]
有人可以告诉我,这段代码有什么问题吗?
答案 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
是一种更安全的方法。