【问题标题】:Fortran DO loop, warning to use integer onlyFortran DO 循环,警告仅使用整数
【发布时间】:2015-06-08 11:13:08
【问题描述】:

我在我的 Ubuntu 15.04 系统上安装了 gfortran。在编译 Fortran 代码时,DO 循环要求仅采用整数参数,而不是实数值或变量。这包括循环变量和步骤表达式。为什么它也不能取真实值?

下面的程序取自here嵌套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

【问题讨论】:

  • 我已经回答说,符合 Fortran 的程序必须使用整数变量/表达式,但请注意,您的编译器很乐意使用实数。这些只是警告。我强烈建议您注意,但它仍然是您的非便携式选择。
  • 哦,对了!这是一个警告。很好地指出。伟大的。谢谢。但是为什么说它不便携呢?
  • 它是不可移植的,因为 Fortran 95+ 编译器不需要接受该程序,因为它不遵循标准指定的规则。许多当前具有 Fortran 77/90 传统的编译器可能都有代码可以接受它,但我不会努力将其放入全新的编译器中。
  • 不是我推荐的,但您可以转换为 do while 循环(假设您想尝试模仿一些旧代码的行为)
  • 有趣的是,教程声称代码是 F95+ .. 有人应该让他们知道。 (他们希望你“注册”只是为了给他们发个便条)

标签: fortran fortran90 gfortran fortran95


【解决方案1】:

Fortran 标准现在要求 do 构造的循环控制由(标量)整数表达式给出,并且循环变量是(标量)整数变量。循环控制由 start、step 和 stop 表达式组成(您的 step 表达式是 0.5)。请参阅 Fortran 2008 文档的 R818 和 R819 (8.1.6.2)。那么,这就是简短而简单的答案:标准是这样说的。

正如编译器的消息所暗示的那样,它比这要复杂一些。直到 Fortran 95 之前,Fortran 中都存在使用其他形式的循环控制。也就是说,从 Fortran 95 开始,使用实数表达式是一项已删除的功能。

使用实数表达式有什么危害?使用得当,可想而知,没有坏处。但是它们的便携性确实存在困难。

考虑

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

多少次迭代?那将是(根据 Fortran 90 的规则)MAX(INT((m2 – m1 + m3) / m3), 0) 其中(m1 是起始值(0.),m2 是停止值(1.)和m3 是步长值(@987654329 @))。那是 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

【讨论】:

  • 但它必须是 10。不是吗?我认为 fortran 不会将其评估为 9 或 11。
  • 0.1 在许多实现中不能完全表示。如果确切的值是 0.9999 或 1.00001,那么您会得到不同的迭代计数,并且从一个确切的值确实是 0.1 的迭代计数中得到。请注意,INT 是用截断定义的,而不是最接近的舍入。
  • [上面还有一个完全一致的错误:天真的答案是 11。]
  • 如果 .1 加法稍微向上取整,您将获得 10 次迭代,在略高于 0.9 处停止。如果它精确或略微向下舍入,您将获得预期的 11 次迭代。我不明白它怎么可能是 9。
  • @agentp 我的评论确实是错误的。我奇怪的一点是,您“稍微”不知道。这将是一个糟糕的实现,但它可能会发生。其他情况可能比这更极端。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 2018-06-05
相关资源
最近更新 更多