аритметична грешка: плаващ незаконен операнд [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-битови серии от 1s и 0s правят валиден IEEE float32 (стойностите "float", използвани в 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(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() и размера на float, за да определите дали във файла има достатъчно данни за четене на ред.

person sappjw    schedule 11.09.2013