我试图用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'不在程序的其他部分使用。您能否想一想可能导致问题的原因?
答案 0 :(得分:1)
如您所见,对于每个(1)和(2),delta的值将恢复为 2 * tolerr = 2E-2。
对于您的功能的前五次调用,xdelta
实际上低于tolerr
。因此,while循环退出,你看到的下一个“(1)”是对该函数的下一次调用,因此将xdelta
重置为0.02
。
当在第六次迭代时不满足标准时,xdelta
的值将保留在循环“循环”中,如您所料。此时,您还有其他与算法相关的问题。有关算法的说明,请参阅MathWorld或WikiPedia。
此外,zerok(xk,xb,func)
行表明zerok
是一个函数,但它只是隐式定义。如果您希望简化将来的调试,Fortran有更明确的方法来定义接口。寻找“Fortran模块”和“接口”。
编辑:更改对zerok