Haskell: 从二进制文件中读取 [Double]
Haskell: read [Double] from binary file
我有一个包含二进制数据的文件(更准确地说,它是一个 npy 文件 = header 数据 + 原始二进制数据)。此数据([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]
谁能告诉我这段代码有什么问题吗?
您应该尝试 cereal
包 (link) 中的 getFloat...
和 getDouble...
函数。
您的代码正在执行的操作是读取 64 位整数值并将其转换为 Double。
不幸的是,什么应该起作用
v <- get :: Double
没有,因为 Data.Binary
不使用双精度的 IEEE754 编码(它存储 decodeFloat
的结果)。因此,一个不错的选择是使用谷物包。至少在 GHC 中,我已经 unsafeCoerce
在 Word64
上完成类似的任务。
bitsToDouble :: Word64 -> Double
bitsToDouble = unsafeCoerce
可能 cereal
是一种更安全的方法。
我有一个包含二进制数据的文件(更准确地说,它是一个 npy 文件 = header 数据 + 原始二进制数据)。此数据([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]
谁能告诉我这段代码有什么问题吗?
您应该尝试 cereal
包 (link) 中的 getFloat...
和 getDouble...
函数。
您的代码正在执行的操作是读取 64 位整数值并将其转换为 Double。
不幸的是,什么应该起作用
v <- get :: Double
没有,因为 Data.Binary
不使用双精度的 IEEE754 编码(它存储 decodeFloat
的结果)。因此,一个不错的选择是使用谷物包。至少在 GHC 中,我已经 unsafeCoerce
在 Word64
上完成类似的任务。
bitsToDouble :: Word64 -> Double
bitsToDouble = unsafeCoerce
可能 cereal
是一种更安全的方法。