我遇到了关于loacal变量初始化的问题。
我有以下函数来计算gammar
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没有初始化为零?
非常感谢
此致 柯
答案 0 :(得分:1)
除非您有一个语句来初始化过程中的局部变量,例如您已注释掉的gz = 0
,否则在调用过程时不会初始化这些局部变量。他们的价值观未定义。它们可以具有从先前调用中留下的值,或者某个随机值。
如果您使用编译器的完整警告选项,它可能会告诉您此问题。 gfortran在编译时警告过一个未初始化的变量。 ifort在运行时检测到问题。
另一种初始化方法是声明。这仍然不会重复该过程的其他调用的初始化。如果在具有声明的过程中初始化局部变量(例如integer :: count = 0
),则仅在过程的第一次调用时执行初始化。但是......变量仍然被定义,并且在下一次调用时将保留它在前一次调用退出时所具有的值。
P.S。 real(8)
不是获取双精度实数的可移植方法。语言标准没有为种类指定特定的数值...编译器可以随意使用任何值。大多数编译器使用字节数,但使用其他编号方法。最好使用selected_real_kind
或ISO_FORTRAN_ENV
和(对于双精度)real64
。见quad precision in gfortran
P.P.S。使用gfortran尝试此代码,该编译器指出了gz
的另一个问题:
function gammar(z) result(gz)
1
Error: Symbol at (1) is not a DUMMY variable
请删除声明中的intent(out)
。