0

ローカル変数の初期化に関する驚くべき問題に遭遇しました。

ガンマーを計算する次の関数を取得しました

function gammar(z) result(gz)
implicit none
real(8),intent(out)::gz
real(8)::z,t,low,up
real(8),parameter::increment=1.0
real(8),parameter::lower_t=0.0,upper_t=10.0
integer(4)::i,n
!gz=0.0
n=(upper_t-lower_t)/increment
do i=1,n
low=lower_t+(i-1)*increment
up=lower_t+(i)*increment
gz=gz+(f(z,low)+f(z,up))*increment/2.0
end do
end function gammar

Then I call this function in main program like
df=9.0
t=0.0
write(*,*) gammar((df+1.0)/2.0)/sqrt(pi*df)/gammar(df/2.0)

答えを間違えた!! 0.126 その理由は、gammar((df+1.0)/2.0) が計算された後、ローカル変数 gz が 0 に設定されていないことがわかりました。したがって、gammar(df/2.0) を計算すると、gz はまだ古い値 24 を保持していました。最終的に,gammar(df/2.0) の答えが間違っていました 34.. ガンマー関数に gz=0.0 を追加すると、この問題は修正されました。これは本当に驚くべきことです。ガンマーが毎回呼び出されたときにローカル gz がゼロに初期化されなかったのはなぜですか?

どうもありがとう

よろしくケ

4

1 に答える 1

1

gz = 0コメントアウトしたなど、プロシージャ内のローカル変数を初期化するステートメントがない限り、これらのローカル変数は、プロシージャが呼び出されたときに初期化されません。それらの値は未定義です。それらは、以前の呼び出しから残った値、または何らかのランダムな値を持つ可能性があります。

コンパイラの完全な警告オプションを使用すると、この問題が通知される可能性があります。gfortran は、コンパイル時に初期化されていない変数について警告しました。ifort は実行時に問題を検出しました。

もう 1 つの初期化方法は、宣言によるものです。それでも、プロシージャの追加の呼び出しの初期化は繰り返されません。などの宣言を使用してプロシージャ内のローカル変数を初期化する場合integer :: count = 0、その初期化はプロシージャの最初の呼び出しでのみ行われます。しかし...変数は定義されたままであり、次の呼び出しでは、前の呼び出しが終了したときの値が保持されます。

PS real(8)は、倍精度実数を取得する移植可能な方法ではありません。言語標準は、種類の特定の数値を指定していません...コンパイラは、希望する値を自由に指定できます。ほとんどのコンパイラはバイト数を使用しますが、他の番号付け方法を使用します。selected_real_kindorISO_FORTRAN_ENVと (倍精度の場合)を使用することをお勧めしますreal64gfortran の 4 倍精度を参照してください

PPS gfortran でこのコードを試してみると、そのコンパイラは別の問題を指摘していgzます:

function gammar(z) result(gz)
                             1
Error: Symbol at (1) is not a DUMMY variable

したがってintent(out)、宣言の を削除します。

于 2013-10-13T01:13:12.290 に答える