Fortran

Fortran，可音译为福传，源自于“公式翻译”（Formula Translation）的缩写，它是通用的编译型指令式编程语言，特别适用于数值计算和科学计算。它在1957年由IBM开发出来，是世界上第一个被正式采用并流传至今的高级编程语言。

## 简介

Fortran最初由IBM在1950年代开发，用于科学和工程应用，并随后长时间统治了科学计算编程。它已经在计算密集领域里应用了超过六个年代，比如数值天气预报、有限元分析、计算流体力学、地球物理学、计算物理学、晶体学和计算化学。它是高性能计算的流行语言，并被用于世界上最快超级计算机的基准测试和排名。

Fortran有很多版本，每个都增加扩展却在很大程度上保持与前面版本的兼容性。后续版本已经增加支持了：结构化编程和基于字符数据的处理（FORTRAN 77），阵列编程、模块化编程和泛型编程（Fortran 90），高性能Fortran (Fortran 95），面向对象编程（Fortran 2003），并发计算（Fortran 2008）和天然的并行计算能力（Coarray Fortran 2008/2018）。

Fortran的设计是很多其他语言的基础。其中最周知的是在1964年推出的BASIC，它基于了FORTRAN II，具有一些语法 (编程语言)清理，尤其是更好的逻辑结构，和其他在交互式环境中使工作更加容易的变更。

## 起源

<image>

在1953年后期，约翰·巴科斯（John W. Backus）向他在IBM的上司提交了一份提案，要为编程他们的IBM 704主机，而开发一种更实用的语言以替代汇编语言。历史上Backus的团队包括了程序员Richard Goldberg、Sheldon F. Best、Harlan Herrick、Peter Sheridan、Roy Nutt、Robert Nelson、Irving Ziller、Harold Stern、Lois Haibt和David Sayre。它的概念包括更容易的将方程录入计算机，这是J. Halcombe Laning发展出的想法，并且在1952年演示于Laning与Zierler系统之中。

在1954年11月，Backus等人完成了草案规定《IBM数学公式转译系统FORTRAN》，第一本FORTRAN手册出现在1956年10月，随后在1957年4月交付了第一个FORTRAN编译器。这是第一个优化编译器，因为客户不情愿使用高级编程语言，除非它的编译器能够生成接近于手工编码汇编语言性能的代码。

尽管编程社区质疑新方法能否胜过手工编码，它将操作一台机器所需的编程语句数目缩减了20倍，因而快速的获得了接受。John Backus在1979年与IBM 雇员杂志《Think》的一次访谈中说道：“我的多数工作出于懒惰。我不喜欢写程序，所以当我工作在IBM 701上，为计算弹道轨迹书写程序的时候，我开始制造一个编程系统来使得书写程序更加容易”。

FORTRAN语言被科学家广泛接纳，用来书写数值计算密集程序，这鼓励编译器作者生产可以生成更快和更高效代码的编译器。在语言中包括复数数据类型，使得Fortran特别适合于技术应用比如电子工程。

到了1960年，FORTRAN版本已经可获得于IBM 709、IBM 650、IBM 1620和7090计算机上。FORTRAN流行性的显著增长，刺激了竞争计算机制造商在它们的机器上提供FORTRAN编译器，因此到了1963年，存在了超过40个FORTRAN编译器。故此，FORTRAN被认为是第一个广泛使用的跨平台编程语言。

提供给IBM 1401计算机的FORTRAN，采用了一种创新的63阶段编译器，它完整的运行于只有8000个（六位元）字符的磁芯内存中。这个编译器可以从磁带或者从2200张打孔卡开始运行；它不进一步的使用磁带或磁盘存储。按照Haines的描述，它保持程序在内存中并装载覆盖部分，就地逐步将其转换成可执行形式。此文被重印编辑于两版的《编译器剖析》和IBM手册《Fortran规定和操作过程，IBM 1401》之中。这种可执行形式不完全是机器语言；转而浮点数算术、下标、输入/输出和函数引用是解释执行的，这早先于UCSD Pascal的P-code两个年代。

Fortran的发展平行于编译器构造历史，在理论和编译器设计上的进步，受到为Fortran程序生成高效代码的激励。

### FORTRAN

<image>

最早的FORTRAN版本应用于IBM 704系统上，包含了32个语句：

- `DIMENSION`和`EQUIVALENCE`语句。
- 赋值语句。
- 三态算术IF语句。
- 检查异常情况：`IF ACCUMULATOR OVERFLOW`、`IF QUOTIENT OVERFLOW`和`IF DIVIDE CHECK`；操纵前面板：`SENSE LIGHT`、`IF (SENSE LIGHT)`和`IF (SENSE SWITCH)`。
- 无条件`GO TO`、计算`GO TO`、`ASSIGN`和指派`GO TO`。
- `DO`循环。
- 格式化输入与输出：`FORMAT`、`READ`、`READ INPUT TAPE`、`WRITE OUTPUT TAPE`、`PRINT`和`PUNCH`。
- 非格式化输入与输出: `READ TAPE`、`READ DRUM`、`WRITE TAPE`和`WRITE DRUM`。
- 其他的输入与输出：`END FILE`、`REWIND`和`BACKSPACE`。
- `PAUSE`、`STOP`和`CONTINUE`。
- `FREQUENCY`语句（为编译器提供程序优化提示）。

## 演化

年份｜非正式名字｜ANSI标准｜ISO/IEC标准

1957｜FORTRAN

1958｜FORTRAN II

1958｜FORTRAN III

1961｜FORTRAN IV

1966｜FORTRAN 66｜X3.9-1966

1978｜FORTRAN 77｜X3.9-1978

1991｜Fortran 90｜X3.198-1992｜1539:1991

1997｜Fortran 95｜1539-1:1997

2004｜Fortran 2003｜1539-1:2004

2010｜Fortran 2008｜1539-1:2010

2018｜Fortran 2018｜1539-1:2018

2023｜Fortran 2023｜1539-1:2023

<image>

<image>

### FORTRAN II

1958年IBM又推出FORTRAN II。主要的增强是凭借允许用户书写的子例程和函数，它们通过传递引用的形式参数来返回值，从而支持了过程式编程。`COMMON`语句为子例程提供了访问公共（或称全局）变量的一种方式。增加了如下6个新语句：

- `SUBROUTINE`、`FUNCTION`和`END`。
- `CALL`和`RETURN`。
- `COMMON`。

接下来的几年内，FORTRAN II又继续支援了`DOUBLE PRECISION`和`COMPLEX`数据类型。

早期的FORTRAN编译器在子例程中不支持递归。早期的计算机架构不支持堆栈的概念，当它们直接支持子例程调用的时候，返回位置经常存储在毗邻这个子例程代码的一个固定位置（例如IBM 1130），或一个特定的机器寄存器（IBM 360系列）之中，它们只能在如下条件下允许递归，即由软件来维护一个堆栈，这个返回地址要在进行调用之前存储在堆栈之上，并在这个调用返回之后恢复。尽管没有规定于FORTRAN 77之中，很多F77编译器将其作为一个选项来支持递归，而Burroughs大型系统，设计有内建的递归，而将其作为缺省来支持。它在Fortran 90中通过新关键字`RECURSIVE`而成为标准。

#### 简单的FORTRAN II程序

下面的海伦公式程序, 从磁带盘上读取数据，它包含3个5位整数A、B和C作为输入。这里没有“类型”声明可用：名字开始于I、J、K、L、M或N的变量是“定点数”（就是整数），其他的是浮点数。因为这个例子要处理整数，变量的名字开始于字母“I”。在FORTRAN II中变量名字必须开始于字母，并可以后续着字母和数字二者，直到达到六个字符的限制。如果A、B和C不能表示在平面几何中一个三角形的边，程序将结束执行，`STOP`给出错误代码“1”。否则输出一行来显示A、B和C的输入值，随后是计算出的作为浮点数的三角形的面积AREA，它占据输出行的10个空位，并显示小数点后2位，这指定于标号904的`FORMAT`语句中的“F10.2”。

```fortranfixed
C     通过标准的平方根函数计算三角形面积
C     输入 - 磁带读写器单元5，整数输入
C     输出 - 行式打印机，实数输出
C     输入错误 - 输出错误信息并显示错误代码1于作业控制列表中
      READ INPUT TAPE 5, 901, IA, IB, IC
  901 FORMAT (3I5)
C     IA、IB和IC不可以是负数或零
C     一个三角形的两条边的总和必须大于第三边
      IF (IA) 110, 110, 101
  101 IF (IB) 110, 110, 102
  102 IF (IC) 110, 110, 103
  103 IF (IA+IB-IC) 120, 120, 104
  104 IF (IA+IC-IB) 120, 120, 105
  105 IF (IB+IC-IA) 120, 120, 199
  110 PRINT 902
  902 FORMAT (42H IA, IB, AND IC MUST BE GREATER THAN ZERO.)
      STOP 1
  120 PRINT 903
  903 FORMAT (50H SUM OF TWO SIDES MUST BE GREATER THAN THIRD SIDE.)
      STOP 1
  199 CONTINUE
C     使用海伦公式计算三角形的面积
      S = FLOATF (IA + IB + IC) / 2.0
      AREA = SQRTF(S * (S - FLOATF(IA)) * (S - FLOATF(IB)) *
     +             (S - FLOATF(IC)))
      PRINT 904, IA, IB, IC, AREA
  904 FORMAT (4H A= ,I5,5H  B= ,I5,5H  C= ,I5,8H  AREA= ,F10.2,
     +        13H SQUARE UNITS)
      STOP
      END
```

### FORTRAN III

IBM继续开发FORTRAN III，至1958年时已允许内建组合语言代码以及其他一些特征；然而这个版本却从未作为产品推出。类似于704 FORTRAN和FORTRAN II，FORTRAN III包含了过多的机器依赖性，造成程式码不易移植到其他机器上的问题。其他厂商提供的早期FORTRAN版本也经常遭受类似的困苦。

### FORTRAN IV

自1961年开始，由于客户的强烈要求，IBM开始发展FORTRAN IV，目的在于移除一些FORTRAN II中过于依赖机器本身的程式码（例如：`READ INPUT TAPE`），同时新增一些新特征，比如`LOGICAL`资料型别（TRUE或者FALSE）、布尔表达式和取代了算术IF语句的逻辑IF语句。FORTRAN IV于1962年推出，最早应用于IBM 7030 Stretch（“Stretch”）计算机之上，接着又推出了IBM 7090和IBM 7094版本，和后来1966年的IBM 1401版本。

到了1965年，FORTRAN IV应该已经符合了美国标准协会X3.4.3 FORTRAN工作组开发的标准。在1966年至1968年之间，IBM为其System/360提供了一些FORTRAN IV编译器，每个都以指示了编译器运行需要的最小内存量的字母来命名。字母F、G、H匹配System/360模式编号来指示内存大小，每个字母增长都是二倍：

- 1966 : FORTRAN IV F for DOS/360（64K字节）
- 1966 : FORTRAN IV G for OS/360（128K字节）
- 1968 : FORTRAN IV H for OS/360（256K字节）

数字设备公司（DEC）在1967年至1975年之间为PDP-10维护了DECSYSTEM-10 Fortran IV（F40）。

大约在这个时候，FORTRAN IV开始成为重要的教育工具和实现，比如滑铁卢大学创造了WATFOR和WATFIV来简化早期编译器复杂的编译和链接过程。

### FORTRAN 66

早期的FORTRAN语言发展史上最重要的一件大事，也许是美国标准协会（即今日的美国国家标准协会ANSI）的委员们，开始为FORTRAN制定标准规格，它名为“美国标准FORTRAN”。1966年委员会推出两套FORTRAN标准版本，分别定义成FORTRAN（基于FORTRAN IV，它已经充任了事实标准），和Basic FORTRAN（基于FORTRAN II，并移除其机器依赖性）。由第一套标准定义的FORTRAN，官方代号为X3.9-1966，后来被称为FORTRAN 66（仍有很多人习惯称之为FORTRAN IV）。FORTRAN 66有效的成为第一套FORTRAN的工业标准版本。FORTRAN 66包括了：

- 主程序、`SUBROUTINE`、`FUNCTION`和`BLOCK DATA`程序单元。
- `INTEGER`、`REAL`、`DOUBLE PRECISION`、`COMPLEX`和`LOGICAL`数据类型。
- `COMMON`、`DIMENSION`和`EQUIVALENCE`语句。
- `DATA`语句，用以指定初始值。
- 内部和`EXTERNAL`（例如库）函数。
- 赋值语句
- 无条件`GO TO`、计算`GO TO`、`ASSIGN`和指派`GO TO`语句。
- 逻辑`IF`和算术（三态）`IF`语句。
- `DO`循环语句。
- `READ`、`WRITE`、`BACKSPACE`、`REWIND`和`ENDFILE`语句，用以处理顺序读写。
- `FORMAT`语句和赋值格式。
- `CALL`、`RETURN`、`PAUSE`、`STOP`和`CONTINUE`语句。
- 霍尔瑞斯常量，用于`DATA`和`FORMAT`语句，作为给子程序的实际参数。
- 最长6个字符的标识符。
- 注释行。
- `END`行。

前面的FORTRAN II版本的海伦公式程序需要进行一些修改来作为FORTRAN 66程序编译。修改包括使用更加机器无关版本的READ和WRITE语句，并移除不再需要的FLOATF类型转换函数。尽管不是必须的，算术IF语句被重写为使用逻辑IF语句，并以更加结构化的方式来表示。

```fortranfixed
C     通过标准的平方根函数计算三角形面积
C     输入 - 单元5的磁带读取器，整数输入
C     输出 - 单元6的行式打印机，实数输出
C     输入错误 - 输出错误信息并显示错误代码1于作业控制列表中
      READ (5, 901) IA, IB, IC
  901 FORMAT (3I5)
C     IA、IB和IC不可以是负数或零
      IF (IA .GT. 0 .AND. IB .GT. 0 .AND. IC .GT. 0) GOTO 110
        WRITE (6, 902)
  902   FORMAT (42H IA, IB, AND IC MUST BE GREATER THAN ZERO.)
        STOP 1
  110 CONTINUE
C     一个三角形的两条边的总和必须大于第三边
      IF (IA+IB-IC .GT. 0 .AND.
     +    IA+IC-IB .GT. 0 .AND.
     +    IB+IC-IA .GT. 0) GOTO 120
        WRITE (6, 903)
  903   FORMAT (50H SUM OF TWO SIDES MUST BE GREATER THAN THIRD SIDE.)
        STOP 1
  120 CONTINUE
C     使用海伦公式计算三角形的面积
      S = (IA + IB + IC) / 2.0
      AREA = SQRT ( S * (S - IA) * (S - IB) * (S - IC))
      WRITE (6, 904) IA, IB, IC, AREA
  904 FORMAT (4H A= ,I5,5H  B= ,I5,5H  C= ,I5,8H  AREA= ,F10.2,
     +        13H SQUARE UNITS)
      STOP
      END
```

### FORTRAN 77

在FORTRAN 66标准推出之后，各家编译器厂商不断推出更具扩充性的标准FORTRAN，促使ANSI委员会X3J3于1969年开始着手于1966标准版本的修订工作，这得到了计算机商业设备制造商协会信息技术标准国际委员会（曾经的BEMA）的赞助。这个修订标准的最终草案于1977年发表，并在1978年4月被正式批准为新的FORTRAN标准。新标准叫做FORTRAN 77，其官方代号是X3.9-1978，它增加了一些重要特征来弥补FORTRAN 66的许多缺点：

- 块状`IF`和`END IF`语句，以及可选的`ELSE`和`ELSE IF`子句，提供改进了的对结构化编程的语言支持。
- `DO`循环扩展，包括参数表达式，负数增量，和零行程计数。
- `OPEN`、`CLOSE`和`INQUIRE`语句，用以改进I/O能力。
- 直接访问文件I/O。
- `IMPLICIT`语句，用来变更或确认对未声明变量的隐含约定，即如果它们的名字开始于I、J、K、L、M或N则是`INTEGER`（否则为`REAL`）。
- `CHARACTER`数据类型，替代了霍尔瑞斯字符串，极大地扩展了字符输入和输出以及对基于字符的数据进行处理的设施。
- `PARAMETER`语句，用以指定常量。
- `SAVE`语句，用以持久保存局部变量。
- 内部函数的通用名称（比如`SQRT`也接受其他类型的实际参数，例如`COMPLEX`或`REAL*16`）。
- 一组内部函数（`LGE`、`LGT`、`LLE`和`LLT`），用于字符串的逻辑比较，它基于了ASCII定序顺序。

在这次标准修订中，一些特征被删除或以使曾经符合标准的程序失效的方式而更改了。尽管在冲突列表的24个项目中的大多数（参见X3.9-1978的附录A2），解决了在以前标准中允许但很少使用的漏洞和病态情况，少量特定功能被特意删除了，比如：

- 霍尔瑞斯常量和霍尔瑞斯数据，例如：`GREET = 12HHELLO THERE!`。
- 在`FORMAT`规定中读入H编辑（霍尔瑞斯字段）描述符。
- 通过下标对数组边界的翻越索引，例如：

```fortranfixed
      DIMENSION A(10,5)
      Y = A(11,1)
```

- 将控制转移出离和回入`DO`循环的范围（也叫做“扩展范围”)。

开发继FORTRAN 77之后的修订标准被反复的推迟，因为标准化过程难以跟上计算和编程实践的快速变化。与此同时，作为“标准FORTRAN”将近十五年，FORTRAN 77成为了编程语言历史上最重要的Fortran方言。

FORTRAN 77版本的海伦公式程序不必需对FORTRAN 66版本程序进行修改。下面的例子展示额外的I/O语句清理，包括使用列表指导（list-directed）的I/O，并将在FORMAT语句中的霍尔瑞斯编辑描述符替代为引述的字符串。它还使用结构化的IF和END IF语句，取代GOTO/CONTINUE语句。

```fortranfixed
      PROGRAM HERON
C     通过标准的平方根函数计算三角形面积
C     输入 - 默认标准输入单元，整数输入
C     输出 - 默认标准输出单元，实数输出
C     输入错误 - 输出错误信息并显示错误代码1于作业控制列表中
      READ (*, *) IA, IB, IC
C     IA、IB和IC不可以是负数或零
      IF (IA .LE. 0 .OR. IB .LE. 0 .OR. IC .LE. 0) THEN
        WRITE (*, *) 'IA, IB, and IC must be greater than zero.'
        STOP 1
      END IF
C     一个三角形的两条边的总和必须大于第三边
      IF (IA+IB-IC .LE. 0 .OR.
     +    IA+IC-IB .LE. 0 .OR.
     +    IB+IC-IA .LE. 0) THEN
        WRITE (*, *) 'Sum of two sides must be greater than third side.'
        STOP 1
      END IF
C     使用海伦公式计算三角形的面积
      S = (IA + IB + IC) / 2.0
      AREA = SQRT ( S * (S - IA) * (S - IB) * (S - IC))
      WRITE (*, 901) IA, IB, IC, AREA
  901 FORMAT (' A= ', I5, '  B= ', I5, '  C= ', I5, '  AREA= ', F10.2,
     +        ' square units')
      STOP
      END
```

### ANSI标准Fortran的扩展

一个重要的FORTRAN 77实用扩展，是1978年发行的MIL-STD-1753。这个由美国国防部制定的规范，标准化了由多数FORTRAN 77编译器实现，却并未引入ANSI FORTRAN 77标准之中的很多特征。这些特征最终合并入Fortran 90标准之中。

- `DO WHILE`、`EXIT`、`CYCLE`和`END DO`语句。
- `INCLUDE`语句。
- `IMPLICIT`语句的`IMPLICIT NONE`变体。
- 位操纵内部函数，基于了包含在工业实时Fortran（ANSI/ISA S61.1 (1976)）中的类似的函数。

1991年推出IEEE 1003.9 POSIX标准，为Fortran-77的程式人员提供了POSIX系统上的呼叫。有超过一百种功能呼叫被定义在文档中。允许访问POSIX相容的进程控制、信号处理、档案系统控制、设备控制、过程定点，以及可移植方式下的串流式输入/输出。

### Fortran 90

FORTRAN 77的被严重推迟的后续版本，非正式名称是Fortran 90，最终在1991年发行为ISO/IEC标准1539:1991，在1992年发行为ANSI标准。除了将官方拼写从FORTRAN改为Fortran之外，这个重大修订版本增加了很多特征，用来反映自从1978年标准以来演变出的编程实践中的重要变化：

- 自由格式源代码输入，不再需要在键入语句之前越过前6个字符位置。
- 小写的Fortran关键字。
- 最长31个字符的标识符（在以前的标准中为6个字符）。
- 行内注释。
- 能够按整体操作数组（或数组节），由此极大地简化了数学和工程计算。
- `WHERE`语句用于选择性数组赋值。
- 数组值的常量和表达式。
- 整体、部分和遮掩的数组赋值和数组表达式，比如

```fortran
X(1:N)=R(1:N)*COS(A(1:N))
```

- 用户定义的数组值的函数和数组构造子。
- `RECURSIVE`过程。
- 模块，将有关联的过程和数据组合在一起，使它们可以被其它程序单元调用，包括限制只允许访问模块的特定部分的能力。
- 极大地改善了参数传递机制，允许在编译时检查接口。
- 用户书写的泛型过程的接口。
- 运算子多载。
- 派生（结构化）数据类型。
- 新的数据类型定义语法，以指定数据类型和变量的其它特性。
- 动态内存分配，通过`ALLOCATABLE`特性和`ALLOCATE`和`DEALLOCATE`语句。
- `POINTER`特性，指针赋值和`NULLIFY`语句，以便于创建和操作动态数据结构。
- 结构化循环构造，使用`END DO`语句用于循环终止，`EXIT`和`CYCLE`语句，用于有秩序地“跳出”正常的`DO`循环迭代。
- `SELECT`...`CASE`构造，用于多路选择。
- 用户控制下可移植的数值精度规定。
- 新的和增强的内部过程。

#### 废弃与删除

不同于以前的修订，在Fortran 90标准文本的附录“B.1 删除特征”中，没有列出任何要删除的特征。任何符合标准的FORTRAN 77程序，在Fortran 90之下也是符合标准的，二者标准都应当能够定义它的行为。

在附录“B.2 废弃特征”中列举了一小组特征，并期望在将来的标准中删除它们。所有这些早期版本特征的功能，都可以用较新的Fortran特征来完成。其中一些为了简化旧程序移植而保留，大多数在Fortran 95中被删除了。

废弃特征｜当前状态

算术`IF`语句｜删除

非整数`DO`形式参数或控制变量｜删除

共享的`DO`循环终止或终止于`END DO`或`CONTINUE`之外的语句｜删除

从块外部分支进入`END IF`｜删除

`PAUSE`语句｜删除

`ASSIGN`语句和指派`GO TO`语句｜删除

赋值的语句编号和`FORMAT`指定符｜删除

H编辑描述符｜删除

替代返回｜废弃

计算`GO TO`语句｜废弃

语句函数｜废弃

在可执行语句之间的`DATA`语句｜废弃

`CHARACTER*`形式的`CHARACTER`声明｜废弃

假定字符长度的函数｜废弃

固定形式的源代码｜废弃

### Fortran 95

Fortran 95正式发表为ISO/IEC 1539-1:1997，它仅是一个小改版，其大部分是修正Fortran 90标准的一些较为显著的问题。虽然如此，Fortran 95仍有不少的扩充，尤其是对高性能Fortran的规定：

- `FOR ALL`和嵌套的`WHERE`结构，用以辅助向量化。
- 用户定义的`PURE`和`ELEMENTAL`过程。
- 派生类型成员的缺省初始化，包括指针初始化。
- 扩展了对数据对象使用初始化表达式的能力。
- 初始化指针至`NULL()`。
- 明确了`ALLOCATABLE`数组的定义，即它们在出离了作用域的时候自动的被释放。

Fortran 95的一个重要补充是ISO技术报告TR-15581：《增强的数据类型设施》，非正式名称是“可分配TR”。这一标准定义了`ALLOCATABLE`数组的增强的应用，先于完全与Fortran 2003兼容的Fortran编译器而投入使用。这些使用包括将`ALLOCATABLE`数组作为派生类型成员、用在过程伪参数列表中以及作为函数返回值。

`ALLOCATABLE`数组比基于`POINTER`的数组更受欢迎，因为`ALLOCATABLE`数组是由Fortran 95提供保证的，当它们退出作用域时会被自动释放掉，避免了内存泄漏的可能性。另外，别名也不再是优化数组引用时的一个问题，可以使编译器生成比用指针时更快的代码。

Fortran 95的第二个补充是ISO技术报告TR-15580：《浮点异常处理》，非正式名称是“IEEE TR”。这一标准定义了对IEEE浮点算术和浮点异常处理的支持。

#### 条件编译和变长字符串

除了强制性的“基础语言”（定义于ISO/IEC 1539-1 : 1997）Fortran 95语言还包括两个可选的模块：

- 变长字符串（ISO/IEC 1539-2 : 2000）。
- 条件编译（ISO/IEC 1539-3 : 1998）。

它们一起构成了多部分的国际标准（ISO/IEC 1539）。

## 现代Fortran

作为由二十一世纪的标准定义的语言，特别是因为它结合了面向对象编程支持和后来的Coarray Fortran，它经常被称为“现代Fortran”，这个术语在文献中的使用日渐增长。

### Fortran 2003

Fortran 2003正式发表为ISO/IEC 1539-1:2004，它是介入了很多新特征的重大修订版本。ISO Fortran工作组（ISO/IEC JTC 1/SC 22/WG5）的官方网站有关于Fortran 2003新特征的详细总结。

据该文所述，本版本的主要改进包括：

- 增强了的派生类型：参数化派生类型，改进的可访问性控制，改进的结构构造子和终止器。
- 支持面向对象编程：类型扩展和继承，多态，动态类型分配，以及类型绑定过程，提供对抽象数据类型的完全支持。
- 改善了数据操纵：可分配的成员（结合了IEEE TR 15581），延迟类型形式参数，`VOLATILE`特性，在数组构造子和分配语句中显式的类型指定，增强的指针，扩展的初始化表达式，增强的内部过程。
- 增强的输入/输出：异步传输，串流访问，用户指定的派生类型的传输操作，用户指定的在格式转换时的舍入控制，预连接单元的命名常量，`FLUSH`语句，关键字的规范化，访问错误信息。
- 过程指针。
- 支持IEEE浮点算法和浮点异常处理（结合了IEEE TR 15580）。
- 与C语言的交互性。
- 支持国际化：访问ISO 10646四字节字符，在数值格式化输入/输出中选择小数点或者逗号。
- 增强与宿主操作系统的集成：访问命令行参数、环境变量和处理器错误信息。

对Fortran 2003的一个重要补充是ISO技术报告TR-19767：《增强的Fortran中模块设施》。这个报告提供了“子模块”，它使得Fortran模块更加类似于Modula-2模块。它们都类似于Ada私有子从单元。这允许模块的规定和实现，可以用分立的程序单元来表达，它改进了大型库的包装，允许尽管发布明确接口却保护商业机密，并防止编译级联。

### Fortran 2008

ISO/IEC 1539-1:2010，非正式的叫做Fortran 2008，于2010年9月通过。它只是一个小改版，略微更正了Fortran 2003的一些问题，并且合并了ISO/IEC TR 19767:2005的子模块功能。新的功能包括：

- 子模块，它是用于模块的补充的结构设施；取代了ISO/IEC TR 19767:2005。
- Coarray Fortran，它是并行执行模型。
- 可伸缩并行构造，用于没有内部依赖性的循环迭代。
- `CONTIGUOUS`特性，用来指定存储格局限制。
- `BLOCK`构造，它可以包含具有构造作用域的对象的声明。
- 递归可分配成员，作为在派生类型中递归指针的替代者。

对Fortran 2008的一个补充是ISO技术规定（TS）29113:2012《进一步的Fortran同C语言的互操作性》，它于2012年5月被提交到ISO并获得批准。这个规定增加对C语言访问数组描述符的支持，并允许忽略实际参数的类型和秩。

### Fortran 2018

Fortran语言的2018年修订版（Fortran 2018）早先称为Fortran 2015，它是一个重大的修订并且发行于2018年11月28日。

Fortran 2018结合了两个此前出版的技术规范：

- ISO/IEC TS 29113:2012《进一步的Fotran同C语言的互操作性》。
- ISO/IEC TS 18508:2015《补充的Fortran并行特征》。

此外的变更和新特征包括支持：ISO/IEC/IEEE 60559:2011（在IEEE 的最新细小修订之前的IEEE浮点数标准）、十六进制输入/输出、`IMPLICIT NONE`增强和其他变更。

### Fortran 2023

Fortran 2023（ISO/IEC 1539-1:2023）发表于2023年11月，可从ISO获得。Fortran 2023是对Fortran 2018的细小扩展，它聚焦于更正Fortran 2018的错误和缺失。它也增加了一些小特征，包括条件表达式和实参、简单过程和枚举类型功能。增加了基于角度和半圈的三角函数。基于角度的三角函数以前是非常常用的厂商扩展。

## Fortran的特征

Fortran语言的最大特征，是接近数学公式的自然描述，在计算机里具有很高的执行效率。Fortran可以直接对矩阵和复数进行运算。其矩阵元素在记忆空间储存次序，采用了行主序和列主序（Column major）次序，Matlab也承袭这点，而C语言则采用行主序和列主序（Row major）次序。

Fortran自诞生以来广泛地应用于数值计算领域，特别是并行计算和高性能计算领域。很多专用的大型数值运算计算机针对Fortran做了优化。Fortran积累了大量高效而可靠的源程序。Fortran 90、Fortran 95、Fortran 2003、Fortran 2008和Fortran 2018的相继推出，使Fortran语言具备了现代高级编程语言的一些特征。

## 代码例子

### Hello World

示例一个在标准输出设备上输出Hello World的简单程序，这种程序通常作为开始学习编程语言时的第一个程序，下面是FORTRAN 77的写法：

```fortranfixed
      PROGRAM HELLO
C     PRINT语句类似WRITE。
C     但是打印到标准输出单元
        PRINT '(A)', 'Hello, world'
        STOP
      END
```

下面是Fortran 90的写法：

```fortran
 program HelloWorld
   write (*,*) 'Hello, world!'   ! 这是个行内注释
 end program HelloWorld
```

### 最大公约数

下面的FORTRAN 77代码例子，使用欧几里德算法计算两个数`A`和`B`的最大公约数：

```fortranfixed
*     euclid.f (FORTRAN 77)
*     使用欧几里德算法找到最大公约数
      PROGRAM EUCLID
        PRINT *, 'A?'
        READ *, NA
        IF (NA.LE.0) THEN
          PRINT *, 'A must be a positive integer.'
          STOP
        END IF
        PRINT *, 'B?'
        READ *, NB
        IF (NB.LE.0) THEN
          PRINT *, 'B must be a positive integer.'
          STOP
        END IF
        PRINT *, 'The GCD of', NA, ' and', NB, ' is', NGCD(NA, NB), '.'
        STOP
      END

      FUNCTION NGCD(NA, NB)
        IA = NA
        IB = NB
   10   IF (IB.NE.0) THEN
          ITEMP = IA
          IA = IB
          IB = MOD(ITEMP, IB)
          GOTO 10
        END IF
        NGCD = IA
        RETURN
      END
```

下面展示编译和运行这个程序的结果：

```console
$ f77 -o euclid euclid.f
$ ./euclid
 A?
24
 B?
36
 The GCD of          24  and          36  is          12 .
```

### Fortran 90特色示例

下面的程序展示动态内存分配和基于数组的运算，这是Fortran 90介入的两个特征。要特别注意的是在操纵数组时，未出现DO循环和IF/THEN语句，数学运算应用于作为整体的数组。同样明显的是运用了描述性变量名字和普通代码格式，这符合当代编程风格。这个例子在交互式录入的数据上计算平均值：

```fortran
program average
  ! 读取一些数值并取其平均
  ! 如下所写，如果没有数据点，返回均值为零
  ! 尽管这可能不是预期行为，它保持例子简单
  implicit none

  real, dimension(:), allocatable :: points
  integer :: number_of_points
  real :: average_points, positive_average, negative_average
  average_points = 0.0
  positive_average = 0.0; negative_average = 0.0

  write (*,*) "Input number of points to average:"
  read  (*,*) number_of_points
  allocate (points(number_of_points))
  write (*,*) "Enter the points to average:"
  read  (*,*) points

  ! 通过总和诸点并除以点数来取平均
  if (number_of_points > 0) average_points = sum(points) / number_of_points

  ! 现在分别只在正数和负数上取平均
  if (count(points > 0.) > 0) &
    positive_average = sum(points, points > 0.) / count(points > 0.)
  if (count(points < 0.) > 0) &
    negative_average = sum(points, points < 0.) / count(points < 0.)

  ! 打印结果到终端标准输出单元6
  write (*,'(a,g12.4)') 'Average = ', average_points
  write (*,'(a,g12.4)') 'Average of positive points = ', positive_average
  write (*,'(a,g12.4)') 'Average of negative points = ', negative_average
  deallocate (points) ! 释放内存
end program average
```

下面展示编译和运行这个程序的结果：

```console
$ gfortran -o average average.f90
$ ./average
 Input number of points to average:
8       
 Enter the points to average:
0 1 -1 2 -2 3 -3 4
Average =   0.5000    
Average of positive points =    2.500    
Average of negative points =   -2.000   
```

## FORTRAN编译器

Windows操作系统下：

- Fortran Power Station 4.0（FPS 4.0），微软公司开发的Fortran编译器。1997年3月转让给DEC公司。
- Digital Visual Fortran（DVF），Fortran Power Station的DEC公司版本，版本号为5.0.x ~ 6.0.x。
- Compaq Visual Fortran（CVF），1998年1月，DEC公司被康柏公司收购，Digital Visual Fortran更名为Compaq Visual Fortran，版本号为6.5.x ~ 6.6.B。2002年5月康柏公司已并入惠普公司，但CVF并未改名，版本号升级到6.6.C。
- Intel Fortran编译器，英特尔公司开发的Fortran编译器。惠普购买了CVF技术之后不久，将Windows平台上的从CVF 6.6.C之后Fortran编译器相关权利全部转售给Intel，它需要微软Visual Studio外壳的支持才能实现Visual IDE功能。在Intel手上的版本编号从7.0开始至现在。
- Absoft Fortran编译器
- Open Watcom
- Silverfrost FTN95，个人用户可免费使用的Fortran 95编译器套件。支持编译为Win32或.NET可执行程序，内置名为Plato的IDE，也可通过插件支持Visual Studio，调试器使用SDBG。

Linux操作系统下：

- The Portland Group，现已被Nvidia收购。
- g77，GNU的Fortran 77编译器，集成在GCC中。
- gfortran，GNU的最新的Fortran编译器，集成在GCC 4.x及以上版本中，目前支持全部Fortran 95、大部分Fortran 2003和Fortran 2008的功能，以替代g77。
- Intel Fortran编译器，它支持Linux操作系统。
- Absoft Fortran编译器
- G95编译器，开放源代码的Fortran 95编译器。
- Sun Studio
- Open64编译器

## FORTRAN数值库

几个著名的Fortran软件包：

- IMSL — 国际数学和统计库的数值库
- 数学核心库 — Intel数学核心库
- NAG数值库 — 数值算法组的数值库
- BLAS — 基本线性代数子程序库
- LAPACK — 线性代数软件包

## 延伸阅读

语言标准

- Informally known as FORTRAN 66.
- Also known as ISO 1539–1980, informally known as FORTRAN 77.
- Informally known as Fortran 90.
- Informally known as Fortran 95. There are a further two parts to this standard. Part 1 has been formally adopted by ANSI.
- Informally known as Fortran 2003.

有关标准

其他参考材料

## 外部链接

- ISO/IEC JTC1/SC22/WG5 —the official home of Fortran standards
- Fortran Standards Documents —GFortran standards
- fortran-lang.org (2020).
- History of FORTRAN and Fortran II —Computer History Museum
- Valmer Norrod, et al.: A self-study course in FORTRAN programing—Volume I—textbook , Computer Science Corporation El Segundo, California (April 1970). NASA (N70-25287).
- Valmer Norrod, Sheldom Blecher, and Martha Horton: A self-study course in FORTRAN programing—Volume II—workbook , NASA CR-1478 (April 1970), NASA (N70-25288).
- An introduction to the Fortran programming language, by Reinhold Bader, Nisarg Patel, Leibniz Supercomputing Centre .
- A coarray tutorial

## 基本资料

- 编程范型：多重范型：指令式、过程式、结构化、面向对象、阵列式、泛型
- 发行时间：1957年
- 设计者：约翰·巴科斯
- 开发者：约翰·巴科斯与IBM
- 软件版本周期：Fortran 2023 (ISO/IEC 1539:2023)
- 软件版本周期：2023年11月17日
- 类型系统：强类型、静态
- 软件实现：GFortran, Intel Fortran编译器, Nvidia/The Portland Group CUDA Fortran, Silverfrost FTN95, Oracle f95, IBM XL Fortran等
- dialects：F (编程语言)
- 受影响于：Speedcoding
- 施影响于：ALGOL 58, PL/I, BASIC, C, PACT I, MUMPS, Ratfor
- 文件扩展名：`.f`, `.for`, `.f90`