арифметическая ошибка: недопустимый плавающий операнд [IDL]

У меня есть этот код:

close, 1 & openr,1,filename,error=err
if (err ne 0) then begin
   close, 1
   n=0
   return
endif

line=fltarr(41)

while(not(eof(1))) do begin
   readf,1,line
endwhile

И в строке readf,1,line я получаю следующую ошибку:

READF: End of file encountered. Unit: 1, File: results
Program caused arithmetic error: Floating illegal operand

Я вижу, в чем причина, и я читал документы об этом, но я все еще не понимаю, какое отношение арифметическая ошибка имеет к EOF (почему EOF? Я проверил, если not(eof(1))) и что делать, чтобы избавиться от этой ошибки. У тебя есть идеи?


person alex    schedule 10.09.2013    source источник


Ответы (2)


Недопустимая операция с плавающей запятой, вероятно, не из not(eof(1)), а из readf, 1, line или перенесена из другой части кода.

Ожидается, что IDL будет считывать 41 32-разрядное значение с плавающей запятой, но некоторые или все считываемые значения не являются допустимыми числами с плавающей запятой. Не все 32-битные последовательности из 1 и 0 составляют допустимое значение IEEE float32 («значения с плавающей запятой», используемые в IDL и большинстве других языков). Если вы случайно встретите конец файла, велика вероятность того, что некоторые данные, считанные из файла, не впишутся в float32. Когда это произойдет, IDL попытается сделать обоснованное предположение о том, каким числом с плавающей запятой должны быть ваши данные, но это технически не является частью стандарта IEEE, поэтому возникает ошибка Program caused arithmetic error: Floating illegal operand.

Для исследования вы можете попробовать заменить следующий код:

close, 1 & openr, 1, filename, error=err
if (err ne 0) then begin
   close, 1
   n = 0
   return
endif

line = bytarr(41 * 4)

while not(eof(1)) do begin
   readf, 1, line
endwhile

В этом случае, поскольку вы читаете массив байтов вместо массива с плавающей запятой, единственная ошибка должна быть READF: End of file encountered. Unit: 1, File: results.

Другая возможная проблема — использование нестандартного not(eof(1)). В IDL not является побитовым значением not, то есть инвертирует все биты следующего термина. Более подходящим оператором здесь будет «логическое НЕ», ~. Таким образом, вместо not(eof(1)) или not eof(1) рассмотрите возможность использования ~eof(1). В данном конкретном случае это вряд ли имеет значение, так как eof должно возвращать либо 1B, либо 0B, побитовая инверсия которых идентична логической инверсии. Все таки другое дело какую отладку попробовать.

Наконец, возможно, что ошибка Floating illegal operand на самом деле возникла до ошибки READF: End of file encountered. Каким бы неинтуитивным это ни казалось, рассмотрим следующий блок кода:

x = sqrt(-1.0)
print, 'Hello, World.'

Это выводит:

Hello, World.
% Program caused arithmetic error: Floating illegal operand

Обратите внимание, что Hello, World. печатается до ошибки недопустимого операнда с плавающей запятой. Это связано с тем, что IDL на самом деле не сообщает об ошибках с плавающей запятой до тех пор, пока функция не вернется, программа не завершится/не завершится сбоем или не будет вызвана функция check_math(). Чтобы проверить, генерирует ли ваша программа ошибку с плавающей запятой перед этим блоком, поместите print, check_math() в начало блока кода. Если при этом печатается что-либо кроме 0, то перед блоком произошли ошибки с плавающей запятой. Использование check_math() также сбрасывает эти состояния ошибок, поэтому вы можете запретить сообщения об ошибках с плавающей запятой, поместив math_err = check_math() после каждого оператора, который может вызвать ошибку с плавающей запятой.

Вот модифицированная версия исходного кода, которая может обрабатывать все указанные выше ошибки:

math_err = check_math()  ; remove any lingering floating point errors

close, 1
openr, 1, filename, error=err
if err ne 0 then begin
    close, 1
    n = 0
    return
endif

line = fltarr(41)

catch, err  ; return here if a non-math error happens
if err ne 0 then begin

    catch, /cancel  ; prevent infinite loop between catch and message
    if !error_state.name eq 'IDL_M_FILE_EOF' then begin
        ; Handle premature end-of-file here.
    endif else begin
        message, /reissue_last  ; issue non-eof errors normally
    endelse

endif else begin

    while ~eof(1) do begin
        readf, 1, line
        ; Handle new line here.
    endwhile
    catch, /cancel  ; stop error checking

endelse
person Pi Marillion    schedule 18.10.2013

Вероятно, в файле нет четного числа из 41 числа с плавающей запятой. Каждый вызов readf, 1, line будет пытаться считать достаточно данных, чтобы заполнить line. Вместо eof() вы можете использовать fstat() и размер числа с плавающей запятой, чтобы определить, достаточно ли данных в файле для чтения строки.

person sappjw    schedule 11.09.2013