Fortran DO循环,警告仅使用整数

7
我在我的Ubuntu 15.04系统上安装了gfortran。编译Fortran代码时,DO循环要求仅使用整数参数而不是实数值或变量,包括循环变量和步长表达式。为什么它不能使用实数值呢?
以下是从这里获取的程序,属于嵌套do循环部分的3.5练习。
        program  xytab
        implicit none
        !constructs a table of z=x/y for values of x from 1 to 2 and 
        !y from 1 to 4 in  steps of .5
        real         ::   x, y, z 
        print *, '           x           y           z'
        do  x = 1,2
            do y = 1,4,0.5
                z = x/y
                print *, x,y,z
            end do
        end  do
        end  program xytab

编译后显示的错误是:
xytab.f95:8.4:

 do y = 1,4,0.5
    1
Warning: Deleted feature: Loop variable at (1) must be integer
xytab.f95:8.12:

 do y = 1,4,0.5
            1
Warning: Deleted feature: Step expression in DO loop at (1) must be integer
xytab.f95:7.3:

do x = 1,2
   1
Warning: Deleted feature: Loop variable at (1) must be integer

2
我已经回答了,符合Fortran标准的程序必须使用整数变量/表达式,但请注意您的编译器也可以使用实数。这只是警告。我强烈建议您遵守这些警告,但对于您来说,这仍然不是可移植的选项。 - francescalus
哦,没错!那是一个警告。指出得很好。太棒了。谢谢。但是你为什么说它不可移植呢? - MycrofD
1
它是不可移植的,因为Fortran 95+编译器不需要接受该程序,因为它不遵循标准规定的规则。许多当前具有Fortran 77/90遗产的编译器可能具有接受它的代码,但这不是我会努力放入全新编译器中的东西。 - francescalus
虽然我不建议这样做,但你可以将其转换为“do while”循环(比如说你想尝试模仿一些旧代码的行为)。 - agentp
有趣的是,教程声称代码是F95+.. 有人应该让他们知道。 (不过他们希望你“注册”才能给他们发送消息) - agentp
1个回答

16

Fortran标准现在要求do循环的控制由(标量)整数表达式给出,循环变量是(标量)整数变量。循环控制包括起始、步长和停止表达式(您的步长表达式为0.5)。请参见Fortran 2008文档的R818和R819(8.1.6.2)。那么,这就是简短而简单的答案:标准是这样规定的。

实际上比这更加复杂,正如编译器的消息所示。Fortran在Fortran 95之前一直支持使用其他形式的循环控制。也就是说,从Fortran 95开始使用实数表达式是不被支持的功能。

使用实数表达式有什么危害呢?如果使用正确,想象中没有危害。但是在移植性方面确实存在着真正的困难。

考虑以下示例:

do x=0., 1., 0.1
 ...
end do

迭代次数是多少?(按照Fortran 90的规则)为:MAX(INT((m2-m1+m3)/m3), 0),其中 (m1 是起始值 (0.),m2 是结束值 (1.),m3 是步长 (0.1))。这是10还是11(或者甚至是9)?这完全取决于您的数字表示方式:我们要记住 0.1 可能不能准确地表示为实数,并且 INT 在转换成整数时会进行截断。您还需要担心实数的重复相加。

因此,在循环内使用整数并进行一些算术运算。

do y_loop = 0, 6
  y = 1 + y_loop/2.
  ...
end do
或者
y = 1
do
  if (y>4) exit
  ...
  y = y+0.5
end do

最后,你提到了.f90.f95的文件后缀。gfortran不会认为第一个后缀表示遵循Fortran 90标准的源代码(在这种情况下,代码将是正常的)。此外,编译器的消息仅仅是警告,可以使用-std=legacy选项来抑制这些警告。相反,如果使用-std=f95(或更高版本的标准),这些警告将变成错误。


作为一个额外有趣的事实,考虑以下Fortran 90代码片段。

real y
integer i

loop_real: do y=1, 4, 0.5
end do loop_real

loop_integer: do i=1, 4, 0.5
end do loop_integer

虽然名为loop_real的循环是有效的,但名为loop_integer的循环不是。在计算迭代次数时,三个表达式将转换为与循环变量的种类参数相同的种类。INT(0.5)等于0


1
但它必须是10。不是吗?我认为Fortran不会将其计算为9或11。 - MycrofD
2
0.1在许多实现中并不能准确表示。如果精确值为0.9999或1.00001,则得到的迭代次数会与确实为0.1的情况以及彼此之间不同。请注意,INT是使用截断而非最近舍入定义的。 - francescalus
上面有一个偏移错误,此外:天真的答案将是11。 - francescalus
如果.1加上略微舍入,则会得到10次迭代,停止在略微大于0.9的数值。如果精确或稍微向下舍入,则得到预期的11次迭代。我不明白它如何可能是9。 - agentp
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - francescalus
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接