我正在读取一个二进制文件,在其中我知道一个大向量的字节位置,该向量包含以IBM格式(描述为here的4字节实数写的10 ^ 8个数据样本)。
据我所知,Fortran中的实数类型使用更新的IEEE样本格式(符号为1位,指数为8位而不是IBM格式为7位),如here所述。因此,如果假设采用实数格式读取这些实数值,则会给我错误的值,因此我想将每个实数分成4个整数,每个整数占一个字节,然后进行转换以从4个整数字节中获取IEEE样本数据。>
我编写了以下测试程序来研究此问题,在该程序中,我分别在字节位置1和5中声明了一个正实数 a1 = 1876752.76854 和它的负当量 a2 = -a1 (a1和a2声明为4个字节长(种类= 1))。
稍后,我从流文件中读取了相同类型b1和b2的两个实数的相同字节位置,但是我还在相同字节位置中读取了两个整数n1和n2(每个4个字节),以查看是否可以获取从整数类型轻松实现IEEE实类型。我还读取了4个整数(每个1个字节)以使用它们计算IEEE值,如下所示:
program test_real_types
implicit none
integer,parameter :: rk=kind(1.0)
real(rk) :: a1,a2,b1,b2
integer(kind=1) :: bytes1(4),bytes2(4)
integer :: i
integer(kind=4) :: n1,n2
a1=1876752.76854
a2=-a1
open(1,file='reals.dat',access="stream",form="unformatted")
write(1,pos=1) a1
write(1,pos=5) a2
close(1)
open(2,file='reals.dat',access="stream",form="unformatted",status="old")
!! reading byte positions: 1-4
do i=1,4
read(2,pos=i) bytes1(i)
enddo
read(2,pos=1) n1 !! read integer n1 of 4 bytes length in the same position
read(2,pos=1) b1 !! read real (4 bytes) in the same position
!! reading byte positions: 5-8
do i=5,8
read(2,pos=i) bytes2(i)
enddo
read(2,pos=5) n2
read(2,pos=5) b2
write(*,*) 'bytes1 = ',bytes1(1:4)
write(*,*) ' n1 = ',n1
write(*,*) ' b1 = ',b1
write(*,*) 'bytes2 = ',bytes2(1:4)
write(*,*) ' n2 = ',n2
write(*,*) ' b2 = ',b2
end program test_real_types
执行上面的代码后,我得到了以下信息:
bytes1 = -122 24 -27 73
n1 = 1239750790
b1 = 1876752.8
bytes2 = 0 0 0 0
n2 = -907732858
b2 = -1876752.8
结果表明,n2不等于-n1(预期值),但令我惊讶的是,当逐字节读取字节5-8时,它们正确地将b2打印为-b1时,字节5-8都等于零。我试图读取字节9,但是按预期它是空的。
在我可以正确读取a2和非零整数n2的实际值的同时,如何获得5-8位置的零字节的任何帮助吗?
答案 0 :(得分:3)
首先,您的程序存在错误:
% gfortran -O2 -g -Wall -fcheck=all test_real_types.f90
% ./a.out
At line 30 of file test_real_types.f90
Fortran runtime error: Index '5' of dimension 1 of array 'bytes2' above upper bound of 4
修复了明显的错误,并避免使用<10的单位号(通常,这是一个好主意,尽管本质上与您在此处看到的错误无关),我得到了
% ./a.out
bytes1 = -122 24 -27 73
n1 = 1239750790
b1 = 1876752.75
bytes2 = -122 24 -27 -55
n2 = -907732858
b2 = -1876752.75