4 関数副プログラム

4.1 どのような時につかうか

教科書の例にならい、次のような関数を計算する場合、どうするか考えよう。

$\displaystyle f(x)=\begin{cases}\sqrt{1-x^2} & \text{$-1 \le x \le 1$のとき}\\ 0 & \text{それ以外のとき} \end{cases}$ (3)

この関数を1回のみ計算する場合は、IF文を使うことで対処できますが、何回も 計算する場合は厄介です。通常のプログラムでは似たような計算を大量に行 うので、できるだけ同じ処理はまとめたほうが効率的です。先の関数を何億回 も計算することは、決して珍しくありません。

そのために、この関数を定義して、いつでも呼び出せるようにすると便利です。 あたかも、$ \sin(x)$のように$ x$を入れれば、計算してくれるようにすれば非 常に便利です。一つの解決方法が文関数ですが、これは1行で関数を定義 する必要があるので、式(3)のようにIF文を使って、 場合分けが必要の時には使えません。文関数で定義できない複雑な関数を定義す るときに、関数副プログラムを使います。

もう一度、文関数と関数副プログラムの違いをまとめておくと次のようになり ます。

文関数
1行で定義できる簡単な関数のときに使います。また、ていぎ したメインルーチン、あるいは副プログラム以外から呼び出すこ とはできません。
関数副プログラム
複数の行で定義する必要がある複雑な関数のとき に使います。

4.2 実際のプログラム

教科書の例6を用いて説 明しよう。教科書のプログラムは分かりにくいので、実際、通常のプログラマー が記述するように書くと以下のようになります。

メインルーチンを見るだけで、このプログラムの動作が分かると思います。関 数F(X)の値をX=0.5から0.1ステップで1.5まで計算して、書き出していると想 像できます。実際の関数は、関数副プログラムを見ればすぐに分かるようになっ ています。

関数F(X)はどこからでも使うこともでき便利です。同じ処理を何回も書かない ですむということです。これは、関数を変えたい場合、プログラムを書き直す のは1箇所で済みます。これにより、プログラムは分かりやすくなり、作成時 間も非常に短くできます。

 *=======================================================
 * MAIN ROUTINE
 *=======================================================
       PROGRAM MAIN

       DO 10 X=0.5, 1.5, 0.1
         Y=F(X)
        WRITE(6,601) X,Y
   601   FORMAT(2E20.8)
    10 CONTINUE
      
       STOP
       END

 *=======================================================
 *     USEER DEFINEDED FUNCTION
 *=======================================================
       FUNCTION F(X)

       IF(ABS(X).LE.1.0)THEN
         F=SQRT(1.0-X*X)
       ELSE
         F=0.0
       ENDIF

       RETURN
       END

4.3 関数副プログラムの文法

4.3.1 関数の呼び出し

関数は、関数名で呼び出して、算術代入文で変数に入れるのが普通です。関数 名は、組み込み関数と異なれば、任意の名前をつけることができます。実引数 並びは、関数の独立変数で、複数個が許されます。多変数関数に対応している ということです。また、配列も許されます。ただし、実引数と仮引数の数と型 は一致させる必要があります。

同様に、関数の戻り値の型と代入される変数の型も一致させる必要があります。

      型 関数名
      代入される変数=関数名(実引数並び)

関数の計算結果の型は、関数名の型宣言により決まります。もし、型宣言を行 わなければ、暗黙の型宣言になります。型宣言を行った関数副プログラムは、 次のようになります。

 *=======================================================
 * MAIN ROUTINE
 *======================================================= 
      INTEGER WA
      
      I=2
      J=3
      K=WA(I,J)

      STOP
      END

 *=======================================================
 * FUNCTION
 *=======================================================      
      INTEGER FUNCTION WA(M,N)
      
      WA=M+N

      RETURN
      END

4.3.2 関数の定義

関数の定義は以下のように行います。関数の型は、REALやINTEGER等、変数の場合 と同じように書きます。これは、戻り値の型を示します。ただし、これは省略 可能で、その場合は関数名に従い暗黙の型宣言7になります。

仮引数並びと実引数並びは、同じ数で型でなくてはなりません。ただし、引数 の変数名は異なっても、何ら問題はありません。関数の処理の部分は、今まで 学習してきたFORTRANのプログラムを書けばよいのです。計算のみならず、 WRITE文やREAD文も書けます。ただし、最後に関数名に値を代入する必要があ ります。これが戻り値になります。

関数副プログラム内で使われた変数は、引数以外は全く、メインルーチンに影 響を及ぼしません。メインルーチンと同じ名前の変数が使われていても、その 結果が反映されることはありません。

      関数の型 FUNCTION 関数名(仮引数並び)
      宣言文(仮引数などの宣言)
    
    実行文(関数の値を求めるための処理)

    関数名=処理の結果の関数の値

      RETURN
      END

4.4 関数副プログラムの注意事項

呼び出し側の変数と関数副プログラムの変数は、引数を除いて完全に独立です。 引数は、その並び方の順序で、呼び出した側と呼ばれた側で完全に一致します。 これを、以下の例をもって、示します。

 *=======================================================
 * MAIN ROUTINE
 *=======================================================
       INTEGER WA

       I=2
       J=3
       K=4
       M=WA(I,J)

       WRITE(6,601)I,J,K,M
   601 FORMAT('I=',I2,'  J=',I2,'  K=',I2,'  M=',I2)

       STOP
       END

 *=======================================================
 * FUNCTION
 *=======================================================
       INTEGER FUNCTION WA(M,N)
       INTEGER I,J,K,M,N

       I=99
       J=99
       K=M+N
       WA=K
       M=88
       N=77

       RETURN
       END
このプログラムを実行するとその結果は、
      I=88  J=77  K= 4  M= 5
となります。要するに、引数を除いて、メインルーチンと関数副プログラムの 変数の格納領域は異なるということです。名前が異なっていても、実引数と仮 引数は同じ領域にデータが格納されます。一方、その他の変数は名前が同じで も、異なった領域にデータは格納されます。


ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成19年8月20日


no counter