2013-10-13 3 views
0

Я встретил неожиданную проблему с инициализацией loacal.переменная результата fortran Не инициализированная

Я получил следующие функции для вычисления 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 Я нашел причину после того, как была рассчитана гаммар ((df + 1.0) /2.0), локальная переменная gz не была установлена ​​на 0. Следовательно, при вычислении gammar (df/2.0) gz все еще сохранял старое значение 24 . В конце концов, gammar (df/2.0) получил неправильный ответ 34 .. Если я добавлю gz = 0.0 в функцию гаммара, эта проблема была исправлена. Это действительно удивительно. Почему локальный gz не был инициализирован до нуля, когда гаммар вызывал каждый раз?

Большое спасибо

С уважением Ke

ответ

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) в декларации.

Смежные вопросы