跳转到内容

Fortran/Fortran 概述

来自维基教科书,开放世界中的开放书籍

作为 Fortran 维基教科书的一部分

本节是对从其他语言转向 Fortran 的快速参考。

常见错误

[编辑 | 编辑源代码]

以下是 C 或 Java 用户在使用 Fortran 时常犯的一些错误

  • 也许从一种语言切换到另一种语言时最常见的错误是试图让新语言看起来或行为过于像先前使用的语言。当切换到 Fortran(无论出于何种原因)时,请考虑以 Fortran 的方式做事,而不是像你在其他语言中那样。
  • 在 Fortran 中,变量不需要声明。以 `I` 到 `N`(“in”组)开头的新的变量是 `INTEGER`。以其他字母开头的变量是 `REAL`。因此,缺点是打字错误会导致新的变量。优点是编码快速且容易,因为在大多数情况下,不需要声明变量。如果您希望 Fortran 像需要声明的语言一样工作,请在每个程序、函数和子程序的顶部使用 `IMPLICIT NONE`。
  • 数组从 1 到 `N` 索引,而不是从 0 到 `N`-1。
  • 传递给函数和子程序的参数按引用传递,而不是按值传递。此外,像 C 这样的语言通常将它们的参数推送到堆栈上。许多(如果不是大多数)Fortran 实现构建一个参数地址数组,并将该数组的地址(仅)推送到堆栈上。这使用略多一些的存储空间,但如果你平均超过 1 个参数,则执行的代码更少。C 用户错误发生在您认为您知道参数引用的地址时。
  • 请注意,参数可能需要声明,也可能不需要声明,这取决于上面的规则。
  • 对于固定形式的代码,前 6 列具有特殊含义,并且您只能使用前 72 列。
  • 尝试过度使用分配。在 Fortran 中,尽量在可能的情况下使用数组的静态分配。
  • 以为你知道变量的大小 - 以下是规则:`LOGICAL` 可以是任意数量的字节。`INTEGER` 至少与 `LOGICAL` 一样大。`REAL` 至少与 `INTEGER` 一样大。`DOUBLE PRECISION` 至少与 `REAL` 一样大。最后,`COMPLEX` 是 `REAL` 的两倍大。通常,大小分别为 1、4、4、8 和 8 个字节,但如果你正在编写可移植代码,不要依赖于此。一个相关的错误是以为 `LOGICAL*4` 或 `REAL*8` 会给你 4 或 8 字节宽的数据。`*` 后面的数字是一个建议,而不是一个要求。

C / C++

int i;
double x[3];
double *y = NULL;
y = new double[3];
delete[] y;
{ 1, 2, 3}; // <- Do the semantics match exactly?

Fortran(带有两个分配和释放的示例 - 不要同时使用这两个示例)

INTEGER i
DOUBLE PRECISION x(3)
DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: xx
DOUBLE PRECISION, POINTER, DIMENSION(:) :: y => null()
ALLOCATE(xx(3))
DEALLOCATE(xx)
ALLOCATE(y(3))                    ! memory allocation for pointer - similar syntax to array allocation
DEALLOCATE(y)                     ! again similar syntax as for array allocation / deallocation 
(/ 1, 2, 3 /)

警告:Fortran 的数组比普通的 C 数组更灵活。默认情况下,它们从 1 而不是 0 索引。

它们可以被声明为通过不同的方式索引

REAL, DIMENSION(-2:10) :: A

这意味着你可以使用 A(10) 以及 A(-2)。

多维数组应该以这种方式声明

REAL A(5,7,10)

你将拥有从 A(1,1,1) 到 A(5,7,10) 的 5*7*10 个元素。请注意,内存的布局对于 Fortran 是唯一的。内存中紧随 A(1,1,1) 的元素是 A(2,1,1),而不是 A(1,1,2)。

你可以通过这种方式使用数组的一部分

REAL A(10,10)
REAL B(3,3)
B(1:3,2:3)=A(4:6,7:8)

将充当

DO i=1,3
  DO j=2,3
    B(i,j)=A(i+3,j+5)
  END DO
END DO

这与过时的但更短的形式相同

DO 1 i=1,3
  DO 1 j=2,3
    1 B(i,j)=A(i+3,j+5)

函数 & 子程序

[编辑 | 编辑源代码]

在 Fortran 中,`FUNCTION` 返回一个值,而 `SUBROUTINE` 不返回。在 C/C++ 中,这仅仅是返回值或返回 `void` 的区别。在 Fortran 中,函数的名称被分配为从函数返回一个值。在调用时,子程序使用 `CALL` 关键字调用,而函数像在 C/C++ 中一样调用。如果没有参数,则不需要空括号。

C/C++

int foo(int i, int j) {
  ...
  return 42;
}
// then later:
int x = foo(1, 2);

Fortran

INTEGER FUNCTION foo(i, j)
...
foo = 42
END
C then later:
k = foo(1, 2)

C/C++

void bar(double j) {
  ...
}
void baz() {
  ...
  return; // Can return in the middle.
  ...
  return; // Optional for a function returning void.
}
// then later:
bar(42.0);
baz();

Fortran

SUBROUTINE bar(x)
...
RETURN
...
END
SUBROUTINE baz
...
END
C then later:
CALL bar(42.0)
CALL baz

控制结构

[编辑 | 编辑源代码]

if → if, then, else, end if

[编辑 | 编辑源代码]

C / C++

if (...) {
  ... 
} else if ( ... ) { 
  ...
} else { 
  ...
}

Fortran

if (...) then
   ...
else if (...) then
  ...
else
  ...
end if

switch → select case, case, end select

[编辑 | 编辑源代码]

C/C++

switch (...) {
case ...:
  ...;
  break; // Without "break", control "falls through" to the next case.
default: // The "default" case is optional but advisable.
  ...;
  break; // Not necessary for the last case.
}

Fortran

select case(...)
   case (...)
      ...
   case default
      ...
end select

for → do, end do

[编辑 | 编辑源代码]

C/C++

for (i = 1; i <= 10; i++) { ... }

Fortran

do i=1,10
   ...
end do
[编辑 | 编辑源代码]
华夏公益教科书