Чтение потоковых двоичных файлов в Фортране - PullRequest
0 голосов
/ 29 июня 2018

Я читаю двоичный файл, в котором я знаю байтовые позиции большого вектора, который содержит более 10 ^ 8 выборок данных, записанных в 4-байтовом вещественном числе в формате IBM (описано здесь ).

Насколько мне известно, реальные типы в Фортране используют более поздний формат выборок IEEE (1 бит для знака, 8 бит для показателя вместо 7-битного показателя для формата IBM), как описано здесь . Поэтому чтение этих реальных значений в предположении, что реальный формат даст мне неправильные значения, поэтому я хочу разделить каждое действительное число на 4 целых числа, каждое из которых занимает один байт, и затем выполнить преобразование, чтобы получить данные образца IEEE из 4 байтов целого числа.

Я написал следующую тестовую программу, чтобы исследовать это, где я объявляю положительное действительное число a1 = 1876752.76854 и его отрицательный эквивалент a2 = -a1 в байтовые позиции 1 и 5 соответственно (a1 и a2 были объявлены длиной 4 байта (kind = 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. Я пытался прочитать байт 9, но он, как и ожидалось, пуст.

Любая помощь в том, как я получаю нулевые байты для местоположений 5-8, в то время как я могу правильно прочитать реальное значение a2 и ненулевое целое число n2?

1 Ответ

0 голосов
/ 29 июня 2018

Прежде всего, ваша программа глючит:

% 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 (что в целом хорошая идея, хотя само по себе не относящееся к ошибке, которую вы видите здесь), я получаю </p>

% ./a.out      
 bytes1 =  -122   24  -27   73
     n1 =   1239750790
     b1 =    1876752.75    
 bytes2 =  -122   24  -27  -55
     n2 =   -907732858
     b2 =   -1876752.75    
...