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.. 如果我在 gammar 函数中添加 gz=0.0,这个问题就解决了。这真是令人惊讶。为什么每次调用 gammar 时本地 gz 没有初始化为零?

非常感谢

问候柯

4

1 回答 1

1

除非您有一个语句来初始化过程中的局部变量,例如gz = 0您已注释掉的语句,否则在调用过程时不会初始化这些局部变量。它们的值是未定义的。它们可能有一个先前调用留下的值,或者一些随机值。

如果您使用编译器的完整警告选项,它可能会告诉您这个问题。gfortran 在编译时警告未初始化的变量。ifort 在运行时检测到问题。

另一种初始化方法是使用声明。这仍然不会重复过程的其他调用的初始化。如果您在带有声明的过程中初始化局部变量,例如integer :: count = 0,则该初始化仅在过程的第一次调用时完成。但是......该变量保持定义,并且在下一次调用时将保留前一次调用退出时的值。

PS real(8)不是获得双精度实数的可移植方式。语言标准没有为种类指定特定的数值......编译器可以自由选择他们想要的任何值。大多数编译器使用字节数,但使用其他编号方法。最好使用selected_real_kindor the ISO_FORTRAN_ENVand (for double precision) real64在 gfortran 中查看四精度

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 回答