0

我有这个代码:

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?我检查了 if not(eof(1)))以及如何摆脱这个错误。你有什么想法?

4

2 回答 2

1

非法浮点运算可能不是来自代码的另一部分,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(eof(1))or not eof(1),考虑使用~eof(1). 在这种特殊情况下,这不太重要,因为eof应该返回1Bor 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 实际上不会报告浮点错误,直到函数返回、程序结束/崩溃或函数被调用。要检查您的程序是否在此块之前生成浮点错误,请将其放在代码块的顶部。如果这样做会打印除 0 以外的任何内容,则表示在块之前发生了浮点错误。使用还会重置这些错误状态,因此您可以通过在每个可能导致浮点错误的语句之后放置浮点错误消息。check_math()print, check_math()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
于 2013-10-18T01:19:21.623 回答
0

文件中可能没有偶数个 41 个浮点数。每次调用readf, 1, line都会尝试读取足够的数据来填充line。代替eof(),您可以使用fstat()浮点数的大小来确定文件中是否有足够的数据来读取一行。

于 2013-09-11T12:34:44.213 回答