在Fortran中更新变量while while循环

时间:2017-09-28 15:13:47

标签: loops while-loop fortran

我试图用Fortran 90编写的代码修复问题,试图通过割线方法求解非线性方程。像往常一样,它会迭代,直到两次后续迭代之间的差异(称为' xdelta')小于固定容差(' tolerr = 1.0e-2')。 但DO WHILE循环似乎没有更新delta的值,并且任何时候循环重新启动delta都会获取其初始值(我通常将其固定为2 * tolerr):

real(kind = 8)function secant(xa,xb,func)!这个程序找到写在外部函数中的泛型方程f(x)= 0的解决方案" f_x":

real(kind=8) function secant(xa,xb,func)
implicit none
integer :: k,iter
real(kind=8) :: zerok,xa,xb,xdelta,tolerr,xkp1,xk
real(kind=8), external :: func
tolerr=1.0d-2
xdelta=2.0d0*tolerr
xk=xa
do while (xdelta>tolerr)
   write(*,*) '(1)',xdelta,abs(xkp1-xk),tolerr
   xkp1=zerok(xk,xb,func)
   write(*,*) '(2)',xdelta,abs(xkp1-xk),tolerr
   xdelta=abs(xkp1-xk)
   write(*,*) '(3)',xdelta,abs(xkp1-xk),tolerr
   xk=xkp1
   write(*,*) '(4)',xdelta,abs(xkp1-xk),tolerr
end do
secant=xk
return
end function secant

我获得以下输出:

(1) 2.0000000000000000E-002 749999.99998890515 1.0000000000000000E-002
(2) 2.0000000000000000E-002 1.5429133782163262E-003 1.0000000000000000E-002
(3) 1.5429133782163262E-003 1.5429133782163262E-003 1.0000000000000000E-002
(4) 1.5429133782163262E-003 0.0000000000000000 1.0000000000000000E-002
(1) 2.0000000000000000E-002 749999.99998890515 1.0000000000000000E-002
(2) 2.0000000000000000E-002 3.2309407833963633E-003 1.0000000000000000E-002
(3) 3.2309407833963633E-003 3.2309407833963633E-003 1.0000000000000000E-002
(4) 3.2309407833963633E-003 0.0000000000000000 1.0000000000000000E-002
(1) 2.0000000000000000E-002 749999.99998890515 1.0000000000000000E-002
(2) 2.0000000000000000E-002 5.0784338964149356E-003 1.0000000000000000E-002
(3) 5.0784338964149356E-003 5.0784338964149356E-003 1.0000000000000000E-002
(4) 5.0784338964149356E-003 0.0000000000000000 1.0000000000000000E-002
(1) 2.0000000000000000E-002 749999.99998890515 1.0000000000000000E-002
(2) 2.0000000000000000E-002 7.1007488295435905E-003 1.0000000000000000E-002
(3) 7.1007488295435905E-003 7.1007488295435905E-003 1.0000000000000000E-002
(4) 7.1007488295435905E-003 0.0000000000000000 1.0000000000000000E-002
(1) 2.0000000000000000E-002 749999.99998890515 1.0000000000000000E-002
(2) 2.0000000000000000E-002 9.3147760489955544E-003 1.0000000000000000E-002
(3) 9.3147760489955544E-003 9.3147760489955544E-003 1.0000000000000000E-002
(4) 9.3147760489955544E-003 0.0000000000000000 1.0000000000000000E-002
(1) 2.0000000000000000E-002 749999.99998890515 1.0000000000000000E-002
(2) 2.0000000000000000E-002 1.1739104287698865E-002 1.0000000000000000E-002
(3) 1.1739104287698865E-002 1.1739104287698865E-002 1.0000000000000000E-002
(4) 1.1739104287698865E-002 0.0000000000000000 1.0000000000000000E-002
(1) 1.1739104287698865E-002 0.0000000000000000 1.0000000000000000E-002
(2) 1.1739104287698865E-002 2813405822.4623795 1.0000000000000000E-002
(3) 2813405822.4623795 2813405822.4623795 1.0000000000000000E-002
(4) 2813405822.4623795 0.0000000000000000 1.0000000000000000E-002
(1) 2813405822.4623795 0.0000000000000000 1.0000000000000000E-002

然后程序停止,因为它给出了分段错误,但由于其他原因,我知道。如您所见,对于每个(1)和(2),delta的值恢复为2 * tolerr = 2e-2。

我认为问题必须在程序的其余部分,因为函数' secant'经常与其他功能合作。名字' xdelta'不在程序的其他部分使用。您能否想一想可能导致问题的原因?

1 个答案:

答案 0 :(得分:1)

  

如您所见,对于每个(1)和(2),delta的值将恢复为   2 * tolerr = 2E-2。

对于您的功能的前五次调用,xdelta实际上低于tolerr。因此,while循环退出,你看到的下一个“(1)”是对该函数的下一次调用,因此将xdelta重置为0.02

当在第六次迭代时不满足标准时,xdelta的值将保留在循环“循环”中,如您所料。此时,您还有其他与算法相关的问题。有关算法的说明,请参阅MathWorldWikiPedia

此外,zerok(xk,xb,func)行表明zerok是一个函数,但它只是隐式定义。如果您希望简化将来的调试,Fortran有更明确的方法来定义接口。寻找“Fortran模块”和“接口”。

编辑:更改对zerok

定义的评论