从文件中读取 16 字节 Fortran 浮点数到 Python
Reading 16 byte Fortran floats into Python from a file
我正在将 Fortran 中的浮点序列写入二进制文件,并希望在 Python 中读取它们。使用单精度和双精度浮点数 (kind=4) 和 (kind=8) 一切正常,但是当我尝试移动到真实的(kind=16)变量类型时,突然事情不再有效(数据数组充满零) .我在这里读到:
np.fromfile 函数需要一个解决方法。我实施了建议的更改,但仍然没有得到正确的结果。 Mwe Python 和 Fortran 代码如下。我用 Python 2.7 + Numpy 1.8 和 Python 3.4 + Numpy 1.14 都尝试了同样的效果。我还检查了生成的文件似乎具有正确数量的数据(480 字节用于 30 个浮点数和 16 字节)。欢迎任何帮助!
Python reader:
import numpy as np
inputfilename = "fortranData.bin"
dp = 8
nVals = 30
with open(inputfilename, 'rb') as f:
# both work fine for 4 or 8 byte floats (32 and 64)
# but not for 16 byte floats (np.float128)
data = np.fromfile(f, dtype=np.float64)
data = np.frombuffer(f.read(dp*nVals), dtype=np.float64, count=nVals)
print(data)
Fortran 编写器(在 Ubuntu 14.04 上用 gfortran 4.8.6 编译)
program test
implicit none
integer, parameter :: dp=8
integer, parameter :: outFileUnit=51, nPts=10, nDim=3
character(len=100) :: binaryFile="fortranData.bin"
real(kind=dp), dimension(nPts,nDim) :: data
integer :: i, j
! - generate data -
do i=1, nPts
do j=1, nDim
data(i,j) = (i-1)*nDim + j
enddo
enddo
! - open file and write data -
open(unit=outFileUnit, file=binaryFile, form='unformatted', access='direct', &
status='replace', recl=nDim*sizeof(data(1,1)))
do i=1, nPts
write(outFileUnit, rec=i) data(i,:)
enddo
end program test
编辑:根据要求,这里是 fortranData.bin 文件顶部的几行数据:
$od fortranData.bin
0000000 000000 000000 000000 000000 000000 000000 000000 037777
0000020 000000 000000 000000 000000 000000 000000 000000 040000
0000040 000000 000000 000000 000000 000000 000000 100000 040000
0000060 000000 000000 000000 000000 000000 000000 000000 040001
0000100 000000 000000 000000 000000 000000 000000 040000 040001
0000120 000000 000000 000000 000000 000000 000000 100000 040001
numpy好像不支持IEEE Quad格式,据我所知需要手动转换一下。例如,如果您以 16 字节的块读取文件,则可以像这样转换块(虽然测试不佳)
def rawQuadToDouble(raw):
asint = int.from_bytes(raw, byteorder='little')
sign = (-1.0) ** (asint >> 127);
exponent = ((asint >> 112) & 0x7FFF) - 16383;
significand = (asint & ((1 << 112) - 1)) | (1 << 112)
return sign * significand * 2.0 ** (exponent - 112)
我正在将 Fortran 中的浮点序列写入二进制文件,并希望在 Python 中读取它们。使用单精度和双精度浮点数 (kind=4) 和 (kind=8) 一切正常,但是当我尝试移动到真实的(kind=16)变量类型时,突然事情不再有效(数据数组充满零) .我在这里读到:
Python reader:
import numpy as np
inputfilename = "fortranData.bin"
dp = 8
nVals = 30
with open(inputfilename, 'rb') as f:
# both work fine for 4 or 8 byte floats (32 and 64)
# but not for 16 byte floats (np.float128)
data = np.fromfile(f, dtype=np.float64)
data = np.frombuffer(f.read(dp*nVals), dtype=np.float64, count=nVals)
print(data)
Fortran 编写器(在 Ubuntu 14.04 上用 gfortran 4.8.6 编译)
program test
implicit none
integer, parameter :: dp=8
integer, parameter :: outFileUnit=51, nPts=10, nDim=3
character(len=100) :: binaryFile="fortranData.bin"
real(kind=dp), dimension(nPts,nDim) :: data
integer :: i, j
! - generate data -
do i=1, nPts
do j=1, nDim
data(i,j) = (i-1)*nDim + j
enddo
enddo
! - open file and write data -
open(unit=outFileUnit, file=binaryFile, form='unformatted', access='direct', &
status='replace', recl=nDim*sizeof(data(1,1)))
do i=1, nPts
write(outFileUnit, rec=i) data(i,:)
enddo
end program test
编辑:根据要求,这里是 fortranData.bin 文件顶部的几行数据:
$od fortranData.bin
0000000 000000 000000 000000 000000 000000 000000 000000 037777
0000020 000000 000000 000000 000000 000000 000000 000000 040000
0000040 000000 000000 000000 000000 000000 000000 100000 040000
0000060 000000 000000 000000 000000 000000 000000 000000 040001
0000100 000000 000000 000000 000000 000000 000000 040000 040001
0000120 000000 000000 000000 000000 000000 000000 100000 040001
numpy好像不支持IEEE Quad格式,据我所知需要手动转换一下。例如,如果您以 16 字节的块读取文件,则可以像这样转换块(虽然测试不佳)
def rawQuadToDouble(raw):
asint = int.from_bytes(raw, byteorder='little')
sign = (-1.0) ** (asint >> 127);
exponent = ((asint >> 112) & 0x7FFF) - 16383;
significand = (asint & ((1 << 112) - 1)) | (1 << 112)
return sign * significand * 2.0 ** (exponent - 112)