在 Fortran IV 中,如何为数组分配单个值?一些 goto 操作是如何处理的? (65的代码阿克曼示例)

问题描述 投票:0回答:1

我的一个非常旧的 Fortran IV (ff66) 程序存在语义问题。这引出了两个问题。 *** 背景 ***

程序应在 O(1) 内存中计算阿克曼函数。它来自这里: 旧纸

这是Henry_Gordon_Rice写的一篇论文(Gordon Rice,wiki页面规定上述论文是他写的)。为什么要读这么老的报纸?为了好玩和作为科学测试。

这里是代码:

 1    INTEGER FUNCTION ACKER(M,N)
 C    Size of VALUE and PLACE tables is one more than LARGEST M EXPECTED (else too long computation)
 2      INTEGER VALUE(6), PLACE(6)
 C    Test ofr Zero M
 3      IF (M .NE. O) GO TO 6
 4      ACKER = N+l
 5      RETURN
 C   Non Zero M INITIALIZE FOR ITERATION
 6      VALUE = 1
 7      PLACE = 0
 C      ITERATION LOOP. GET NEW VALUE.
 8      VALUE = VALUE + 1
 9      PLACE = PLACE + 1
 10     DO 18 I=1,M
 11         IF (PLACE(I) .NE. 1) GO TO 16
 C          INITIATE NEW LEVEL
 12         VALUE(I+1) = VALUE
 13         PLACE(I+1) = 0
 14         IF (I .EQ. M) GO TO 18
 15         GO TO 8
 16         IF (PLACE(I) .NE. VALUE(I+1) GO TO 8
 17         VALUE(I+1) = VALUE
 18         PLACE(I+1)=PLACE(I+1)+1
 C     CHECK FOR END OF ITERATION
 19     IF (PLACE(M+1) .NE. N) GO TO 8
 20     ACKER = VALUE
 21     RETURN
 22  END

并且没有评论。

 1   INTEGER FUNCTION ACKER(M,N)
 2      INTEGER VALUE(6), PLACE(6)
 3      IF (M .NE. O) GO TO 6
 4      ACKER = N+l
 5      RETURN
 6      VALUE = 1
 7      PLACE = 0
 8      VALUE = VALUE + 1
 9      PLACE = PLACE + 1
 10     DO 18 I=1,M
 11         IF (PLACE(I) .NE. 1) GO TO 16
 12         VALUE(I+1) = VALUE
 13         PLACE(I+1) = 0
 14         IF (I .EQ. M) GO TO 18
 15         GO TO 8
 16         IF (PLACE(I) .NE. VALUE(I+1) GO TO 8
 17         VALUE(I+1) = VALUE
 18         PLACE(I+1)=PLACE(I+1)+1
 19     IF (PLACE(M+1) .NE. N) GO TO 8
 20     ACKER = VALUE
 21     RETURN
 22  END

与大多数迭代程序相比,这是一个非常短的程序:

*** 问题***

因此,在阅读代码、了解其工作原理时,有两件事困扰了我: (1) 如果 PLACE 是一个数组/表,那么赋值 PLACE=1 是如何工作的? 1 无处不在? 1 到第一个单元格? PLACE也是一种隐藏索引?
这是关于 PLACE = PLACE + 1 的相同问题。它是如何工作的? (记住 PLACE 不是整数变量而是数组)

(2) DO-LOOP(一种 for 循环)内的一些 GOTO 脱离了 do 循环的范围(主体)。然后代码可以重新进入 do 循环的范围/主体。如果是,变量 J 是否重置?或者是否使用了副本(所以会有一个隐藏的堆栈?)。

提前致谢, 弗雷德里克·加瓦

ps : 有关 Fortran IV 版本的一些参考资料 手册

我尝试将代码转换为 Java,但如果不理解语义,我就做不到。我尝试用“g77 -ff66”编译它,但没有成功。我尝试阅读有关 Fortran IV 和阿克曼函数迭代算法的论文

(我绝对不是 Fortran 程序员...)

arrays fortran variable-assignment goto ackermann
1个回答
0
投票

第 1 部分)

一次分配或使用整个数组是所谓的“数组语法”,仅在 Fortran 90 中引入。据我所知,像

PLACE = 0
这样的东西在 Fortran 66 或 77 中是非法的。所以这里有两个假设:

  • 代码当时依赖于某些编译器的非标准和不可移植的行为,例如
    PLACE
    (可能)是
    PLACE(1)
  • 的快捷方式
  • 有人修改了原始代码以利用 F90 数组语法

但后一种假设不太可能,因为代码还包含类似

VALUE(I+1) = VALUE
的内容,即将整个数组分配给标量元素:这在所有 Fortran 标准中都是非法的,无论是旧的还是新的。

第 2 部分)

使用 goto 语句逃离 do 循环是可以的(在 Fortran 90 之前这是唯一的方法)。在您的示例中,当再次进入 do 循环时,

J
变量只是重置为循环的初始值,并且该变量没有新实例。

授权/未授权的是使用 goto 语句在 do 循环内跳转。

编辑

我认为这是代码的正确版本。

  • 我用对第一个元素的引用替换了所有未索引的数组引用
  • 我修复了一些错误的缩进(这是老式的固定源格式,其中语句必须从第 7 列开始)
  • 我在第 11 行添加了缺少的括号
  • 我在第 14 行将
    GO TO 18
    替换为
    GO TO 19
 1      INTEGER FUNCTION ACKER(M,N)
 2      INTEGER VALUE(6), PLACE(6)
 3      IF (M .NE. O) GO TO 6
 4      ACKER = N+l
 5      RETURN
 6      VALUE(1) = 1
 7      PLACE(1) = 0
 8      VALUE(1) = VALUE(1) + 1
 9      PLACE(1) = PLACE(1) + 1
 10     DO 18 I=1,M
 11         IF (PLACE(I) .NE. 1) GO TO 16
 12         VALUE(I+1) = VALUE(1)
 13         PLACE(I+1) = 0
 14         IF (I .EQ. M) GO TO 19
 15         GO TO 8
 16         IF (PLACE(I) .NE. VALUE(I+1)) GO TO 8
 17         VALUE(I+1) = VALUE(1)
 18         PLACE(I+1)=PLACE(I+1)+1
 19     IF (PLACE(M+1) .NE. N) GO TO 8
 20     ACKER = VALUE(1)
 21     RETURN
 22     END
© www.soinside.com 2019 - 2024. All rights reserved.