FORTRAN 古董代码赏析
欣赏一下下图这段 FORTRAN 77 时代的代码,语句中大量的 GOTO 是那个时代编程的典型特征。
这段代码的功能非常简单: 读入一个整数 MAXINT,然后输出从 2 到 MAXINT 之间的所有素数。
它采用的是最朴素的试除法:对于每个整数 N,从 2 到 N-1 依次尝试。
下面是完整代码,加了一行用户输入提示。
1 | C PROGRAM TO COMPUTE PRIME NUMBERS |
可以用 gfortran 编译运行
1 | gfortran prime.f -o prime |
使用例如
1 | ENTER THE UPPER LIMIT: |
这段代码是典型的古典 FORTRAN 77 编程风格,采用的是传统的固定格式(fixed source form)。在固定格式中,每一列具有特定含义:
- 第 1 列:C 或 * 表示注释行
- 第 1~5 列:语句标签(支持 GOTO 跳转)
- 第 6 列:续行标记
- 第 7~72 列:Fortran 语句
- 第 73~80 列:传统卡片序号,通常被忽略
现代 Fortran 语言更建议源码使用自由格式,两种格式需要区分,可以从文件后缀推断,例如 main..f 和 main.for 通常是固定格式,main.f90 通常是自由格式。
GNU Fortran 提供编译选项 -ffixed-form 和 -ffree-form 来区分固定格式和自由格式,不提供时也会通过后缀推断。
值得注意的是,这段代码的条件语句使用的是算术 IF 语法,格式如下
1 | IF (expr) label_negative, label_zero, label_positive |
其中:
expr < 0跳转到 label1expr = 0跳转到 label2expr > 0跳转到 label3
算术 IF 语法是基于 GOTO 跳转实现的控制语句,虽然直到现在,条件语句在底层 CPU 中仍然是用这种类似的方式实现的,但是高级编程语言都提供了更优雅的结构化语法,例如 C 语言中的 if-else 语句。
算术 IF 在 Fortran 90 中已经被列为过时特性,并在 Fortran 2018 中正式从标准中删除。不过 GNU Fortran、Intel Fortran 等编译器至今仍然支持它,较新版本的可能需要开启额外的兼容性选项。
计算素数表的逻辑其实主要是两层循环和一个整除判断,由于 FORTRAN 77 没有提供结构化的循环语句,循环逻辑还是通过 IF 和 GOTO 语句实现的。
下面给出与上述代码等价的使用现代 Fortran 语言的自由格式版本
1 | program prime |
其中几个值得注意的区别包括:
- 使用小写而非全大写
- 使用
!表示注释而非在第一列的C - 禁止隐式的类型推断
- 使用结构化的
do和if语法替代原本的算术 IF 和 GOTO 跳转