在Fortran中没有预先声明循环计数器



作为作业的一部分,我得到了一个FORTRAN程序的(旧)代码。我只有c++(和Oberon)的经验,我对Fortran的知识是通过各种(部分)教程获得的,这些教程并不总是相互一致的。然而,尽管我有基本的知识,这段代码却因为缺乏优雅和一致性而让我很不舒服。但更令人不安的是:它似乎充满了编程错误。

我想问的特定代码段看起来类似于这个例子:

PROGRAM Foo
  IMPLICIT NONE
  CALL Bar(0.0,-1)
END PROGRAM Foo
SUBROUTINE Bar(t,i)
  DIMENSION(5) :: R = 0.5
  REAL :: s = 0.5
  DO k = 1, 5
     R(k) = k * i
  END DO
  CALL Random(s) ! Random is a well-behaved pseudorandom number generator
                 ! on the interval ]0,1[ implemented elsewhere.
  k = 1 + (s * 5)
  t = R(k)
END SUBROUTINE Bar

我将解释我认为这个想法是什么。Random(s)s中存储一个介于0.0到1.0之间的值。这意味着1 + (s * 5)将产生一个介于1和5之间的实数(pRNG的一些测试表明,它的最大值为~5.992,最小值为~1.0016)。如果左侧是整数,则会自动进行右侧的类型转换,尾数将被截断,在区间[1,5]上留下一个整数值。但是k在任何地方都没有被声明为INTEGER。相反,k被初始化为DO循环的循环计数器。当然,这意味着它必须是一个整数,但我认为这是不好的做法。我说的对吗?另外,我不赞成数组R的声明,因为没有显式的类型说明符。我已经明确表示,它将通过初始化数组来存储REALs,但这在实际代码中没有完成…

当然,我已经调整了实际代码,而不仅仅是初始化,希望遵守更高的标准。(想象一下IMPLICIT变量,不一致的大写和到处都是goto。)此外,也许我可以问这个,而我在它:是现代标准结束程序,子程序和函数与语法END <PROGRAM/SUBROUTINE/FUNCTION> Name ?在我得到的代码中,他们只是使用了END。我一直假设正确的现代语法是我提到的那个,但我不确定。就像我不确定程序等的名称是否应该不大写一样。

你写的基本上是正确的,但有一些事情值得注意。

Rk(以及ti)是隐式类型的受害者,但应该注意的是,这与它们的使用或初始化方式无关。具体来说,R将是一个真实的,而不管=0.5

此外,在Fortran 95之前,循环变量不必是整数。像do a=1,5这样的代码不会强制隐式类型的a为整数(但在Fortran 95+中是不正确的)。

你当然是正确的,现代的品味是在每个作用域单元中都有implicit none -强制所有内容都显式键入。

然而,我会对"正确的现代语法"提出异议:仅以END结束子程序并没有不正确的,但我确实更喜欢并使用更长的形式。

还有两件小事需要注意:显式初始化意味着save属性(在本例中没有实际作用);Random不是标准的内在属性,如果它不能返回0,那么它的行为与标准的random_number不同。

最新更新