今回は非線形方程式
$$e^x = x^2$$
の解を数値計算で解く。今回はニュートン法で求める。
ニュートン法
ある関数\(y = f(x)\)を考える。\(f(x)=0\)に対応する適当な近似解\(x_0\)が最初に与えられたものとする。
次に点\((x_0,f(x_0))\)を通る\(y = f(x)\)の接線方程式
$$y – f(x_0) = f'(x_0)(x-x_0) \tag{1}$$
を考える。式(1)の接線と\(x\)軸の交点を\(x_1\)として新たな近似解とすると、
$$x_1 = x_0 – \frac{f(x_0)}{f'(x_0)}$$
が得られる。同様に、次は点\((x_1,f(x_1))\)を通る\(y = f(x)\)の接線方程式の\(x\)切片\(x_2\)を求め、近似解を更新する。一般に、近似解\(x_{k+1}\)は\(x_{k}\)から
$$x_{k+1} = x_k – \frac{f(x_k)}{f'(x_k)} \tag{2}$$
と求められる。式(2)を繰り返し計算し、\(|x_{k+1}-x_{k}|\)が十分小さい値になると\(x_{k+1}\)は解に収束したとみなす。
ニュートン法は極めて収束が速いが、初期値や\(f(x)\)によっては解が収束しない場合もある。
サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
program newton implicit none real, parameter :: eps = 1.0e-6 integer, parameter :: loopmax = 100 real :: xold,xnew,res real :: f,g integer :: loop write(6,*) 'input x0' read(5,*) xold do loop = 1 , loopmax xnew = xold-f(xold)/g(xold) res = abs(xnew-xold) if(res < eps) exit xold = xnew end do if(res < eps) then write(6,*) 'converge: loop =',loop write(6,*) 'x =',xnew else write(6,*) 'not converge!' end if end program newton real function f(x) implicit none real :: x f = exp(x) - x**2 end function f real function g(x) implicit none real :: x g = exp(x) - 2*x !微分 end function g |
\(f(x) = e^x – x^2\)としている。Newton法では導関数が必要なので、\(g(x) = e^x – 2x\)も定義している。
使い方はターミナルで
1 |
gfortran newton.f90 |
とし、実行して\(x_0\)を代入する。
例えば\(x_0 = 1\)と入力すると、
1 2 |
converge: loop = 6 x = -0.703467429 |
と出力される。
コメント