跳轉到內容

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
[編輯 | 編輯原始碼]
華夏公益教科書