简体   繁体   English

从文件中读取 16 字节 Fortran 浮动到 Python 中

[英]Reading 16 byte Fortran floats into Python from a file

I am writing sequences of floating points from Fortran into binary files and want to read them in Python.我正在将 Fortran 中的浮点序列写入二进制文件,并希望在 Python 中读取它们。 All works fine with single and double precision floats (kind=4) and (kind=8), but when I attempt to move to a real(kind=16) variable type, suddenly things no longer work (data array filled with zeros).使用单精度和双精度浮点数 (kind=4) 和 (kind=8) 都可以正常工作,但是当我尝试移动到真实的 (kind=16) 变量类型时,突然事情不再起作用(数据数组充满零) . I read here: python read 16 bytes long double from binary file That a workaround is needed for the np.fromfile function.我在这里读到: python read 16 bytes long double from binary file np.fromfile 函数需要一种解决方法。 I implemented the suggested change but am still not getting the right result.我实施了建议的更改,但仍然没有得到正确的结果。 Mwe Python and Fortran code is below. Mwe Python 和 Fortran 代码如下。 I tried this both with Python 2.7 + Numpy 1.8 and Python 3.4 + Numpy 1.14 to the same effect.我在 Python 2.7 + Numpy 1.8 和 Python 3.4 + Numpy 1.14 上都尝试过,效果相同。 I also checked and the generated file seems to have the right amount of data (480 bytes for 30 floats with 16 bytes).我还检查了生成的文件似乎有正确的数据量(30 个浮点数为 480 个字节,16 个字节)。 Any help will be welcome!欢迎任何帮助!

Python reader: Python阅读器:

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 writer (compiled with gfortran 4.8.6 on Ubuntu 14.04) 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

EDIT: as requested, here's a few lines of the data at the top of the fortranData.bin file:编辑:根据要求,这里是 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

It seems that numpy does not support the IEEE Quad format, so far as I know it just needs to be converted manually.似乎numpy不支持IEEE Quad格式,据我所知只需要手动转换即可。 For example, if you read the file in chunks of 16 bytes, then the chunks can be converted like this (poorly tested though)例如,如果您以 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM