Как обнаружить NaN в списке направленного ввода в Фортран - PullRequest
2 голосов
/ 19 июня 2019

Я читаю реальные данные из входного файла со списком ввода. Каков наилучший способ обнаружить NaN с помощью iostat=iostatus?

В качестве примера для ввода большой программы мне нужно прочитать файл вроде:

1   NaN    1.0
2   nan    2.0

, где иногда встречаются "NaN" вместо действительных чисел. с READ(ird, *, iostat=iostatus) nr, r1, r2 iostatus не отмечен для gfortran 7.4.0 в UBUNTU!

Видимо, ошибка ввода рассматривается как тихий NaN вместо сигнального NaN. Опции компилятора gfortran, кажется, не предоставляют возможность превратить это в сигнальный NaN. Стандарт Фортрана в https://j3 -fortran.org / документ / год / 18 / 18-007r1.pdf не указывает обработку Нан в списке направленного ввода.

В разделе 13.7.2.3.2 есть информация для форматированного ввода, и в нем конкретно указано, что Nan на входе обрабатывается как тихий NaN.

Я нашел документацию по компилятору NAG, в которой прямо указано, что NaN на входе никогда не помечается как сигнальный NaN.

Философия этих решений в стандарте превосходит меня. Я ожидал, что это будет ошибкой.

Если строка изменена на:

read(ird, *, err=10, iostat=iostatus) nr, r1, r2
10 continue

iostatus меняется на +5001! Но я не хочу возвращаться к древнему предложению err=.

Мне известно, что я могу прочитать строку в символьную строку, проанализировать строку на наличие любого "NaN" и продолжить. Я мог бы, как в примере, проанализировать ieee_is_nan(). Это, однако, кажется излишне утомительным, учитывая предложение iostat=.

Так есть ли опция компилятора, которую я пропустил?

PROGRAM main
USE ieee_arithmetic
IMPLICIT NONE
INTEGER, PARAMETER :: IRD = 12
INTEGER :: iostatus
REAL    :: r1 = -1.0, r2 = -1.0
INTEGER :: nr = 0
CHARACTER(LEN=1024) :: line = ' '

OPEN(UNIT=IRD,FILE='data.data', STATUS='old')

READ(IRD, *, IOSTAT=iostatus, IOMSG=line) nr, r1, r2
WRITE(*,*) iostatus, nr, r1, r2, ieee_is_nan(r1), line(1:LEN_TRIM(line))

r1 = -1.0
r2 = -1.0

READ(IRD, ERR=10, IOSTAT=iostatus, IOMSG=line) nr, r1, r2
10 CONTINUE
WRITE(*,*) iostatus, nr, r1, r2, ieee_is_nan(r1), line(1:LEN_TRIM(line))

CLOSE(UNIT=IRD)
END PROGRAM main

Вывод моей программы: (укороченные незначительные цифры и пробелы)

0  1              NaN   1.00 T 
5001  1  -1.00      -1.00 F
Missing format for FORMATTED data transfer

При первом чтении iostatus устанавливается в 0, а при втором считывании - 5001!

...