5 副程式 Subprogram

5.1 函數 Function

庫存函數 Library Function

函數副程式 FUNCTION Subprograms

FUNCTION 副程式的定義格式如下

type FUNCTION name ( x1, x2, ... , xn )

其中

注意

  1. 函數的引數用以傳送資訊。
  2. 函數值的型式未標示,必須在主體內標示。
  3. 函數名稱必須在主體內出現一次,通常出現在指定敘述的左邊,或輸入名列內。

函數調用

使用函數時,在算術式中列出其名稱及實際引數。 實際引數的數值成為相關的形式引數的數值,並用以計算 函數值。

注意,實際引數的個數和型式,必須和形式引數一致。

例題

  1. Voltage Across a Capacitor

    例題: CAPAC (source)

  2. Factorial Function
  3.        FUNCTION FACTOR (N)
    
           INTEGER FACTOR, N, I
           FACTOR = 1
           DO 10 I = 2, N
               FACTOR = FACTOR * I
    10     CONTINUE
           END
    
    
  4. Pollution Index
  5.        CHARACTER*9 FUNCTION AIR (INDEX)
    
           INTEGER INDEX, CUTOFF
           PARAMETER (CUTOFF = 50)
    
           IF (INDEX .LT. CUTOFF) THEN
               AIR = 'SAFE'
           ELSE
               AIR = 'HAZARDOUS'
           END IF
    
           END
    
    
  6. Poisson probability Function
  7.        FUNCTION POISS (LAMBDA, N)
    
           INTEGER FACTOR, N
           REAL POISS, LAMBDA
    
           POISS = (LAMBDA ** N * EXP(-LAMBDA)) / FACTOR(N)
           END
    

    例題: Poisson probability Function (source)

  8. Simulation
    通常由副程式轉回主程式,副程式的所有 local variable 變成未定。 要保其量值,必須另用 SAVE 敘述。

    例題: Simulate shielding of nuclear reactor (source)

亂數產生器

亂數 (random number) 數列是一串表面上雜亂無章的數字。 數字重複出現的周期必須很長, 而且前後數字似無關聯。 均勻分佈 (uniformly distributed) 的亂數數列,可用下列式子產生

    Xn+1 = (aXn + c) mod m,    n>=0

式中初值 X0, 乘數 a, 增數 c 均不為負, 而且都小於模數 m。

適當選擇 X0, a, c, 和 m 值, 即可產生亂數。 以 32 bits 的計算機為例, 可取 a=3612, c=5701, m=566927。(ref. 3, p.335)

產生亂數的方法有好幾種,這種方法稱為線性同餘法 (linear congruential method)。

FORTRAN 90 -- 使用下列副程式產生亂數:

    CALL RANDOM(X)  產生(0,1)亂數X
    CALL RANDOMSEED 設定亂數產生

References

  1. 程式之秘:演算法(一)
  2. D.E. Knuth, The Art of Computer Programming: Seminumerical Algorithms, vol.2, Ch.3, Addison-Wesley, 1969.
  3. L.P. Meissner and E.I. Organick, FORTRAN 77, Ch.10, Addison-Wesley, 1980.

敘述函數 Statement Function

假如函數可用單一式子界定,則可採用敘述函數定義。

name( x1, x2, ... , xn ) = expr

例如

       POISS(LAMBDA, N) = (LAMBDA ** N * EXP(-LAMBDA)) / FACTOR(N)

例題: HADDER(Binary Half Adder) (source)

5.2 數值方法:求根

Bisection method

例題: BISECT (source)

Newton's method

例題:  NEWTON (source)

5.3 數值方法:積分

例題:  AREA: Rectangle approximation of an integral -- version 1 (source)

5.5 Subroutine 副程式

SUBROUTINE 副程式的定義格式如下

SUBROUTINE name ( x1, x2, ... , xn )

其中

SUBROUTINE 副程式也是一個完整的程式,它和 FUNCTION 副程式不同之處如下

  1. FUNCTION 副程式執行後所得的函數值,送回 CALL 它的程式。 SUBROUTINE 副程式可送回一個或多個值,甚至只進行某些工作而沒有值送回。
  2. SUBROUTINE 副程式之名稱不代表任何值,只是做為識別之用,數值是經由引數送回。 FUNCTION 副程式之名稱代表函數值。
  3. 使用SUBROUTINE 副程式用 CALL 敘述,使用FUNCTION 副程式用函數名稱。

    例如

          CALL PRNDEG(DEGS, MINUTS, SECONS)
    

例題

  1. ANGLE1 : Displaying an Angle in Degrees
  2. (source)
  3. ANGLE2 : Displaying an Angle in Degrees-Minutes-Seconds Format (source)
  4. POLAR : Coordinate Conversion -- version 1 (source)

5.6 Modular Programming

5.7 引數為 Function 和 Subroutine

使用副程式時,實際引數可以是另一副程式名稱。 由於副程式名稱和變數名稱一樣,無法區別, 所以必須使用 EXTERNAL 或 INTRINSIC 敘述予以宣告。

EXTERNAL 敘述

一般用者界定的函數用EXTERNAL 敘述宣告。

例如

      EXTERNAL POLY

例題:  AREA: Rectangle approximation of an integral -- version 2 (source)

INTRINSIC 敘述

庫存函數用INTRINSIC 敘述宣告。

例如

      INTRINSIC SIN

例題:  AREA: Rectangle approximation of an integral -- version 3 (source)

5.8 COMMON 敘述

主程式和副程式間的資料,是依靠引數來傳送。 但是假如所要傳送的資料很多,或相同的資料要在幾個不同 的副程式中使用,這樣的傳送方式就很不方便。 這時適合使用 COMMON 敘述。 COMMON 敘述用以在程式中指定 某些特定的儲存位置為共用區,而各份程式都可直接使用此共用區的儲存位置。

COMMON 敘述的形式有兩種

  1. Blank COMMON
  2. Named COMMON

Blank COMMON

       COMMON list

使用COMMON 敘述的項目,必須注意事項

  1. 相對應項目的型式必須相同。
  2. 假如項目的型式是 CHARACTER,其長度(即字元數)必須相同。
  3. 在使用COMMON 敘述的副程式中,COMMON 敘述的項目不可用做形式引數。

例題 POLAR: Coordinate Conversion -- version 2 (source)

Named COMMON

       COMMON /name-1/ list-1 /name-2/ list-2 ...

FORTRAN 90 -- FUNCTION 和 SUBROUTINE 副程式都可以使用 遞迥式(recursive),例如

    RECURSIVE FUNCTION FACTORIAL(N) RESULT(FACT)
        INTEGER FACTORIAL, RESULT, N
        IF (N<1) THEN
            FACT = 1
        ELSE
            FACT = N * FACTORIAL(N-1)
        END IF
    END