§6.代数方程式

§6.代数方程式
[第11回]
6.1 ベアストウ法
n ≥ 3 の代数方程式の数値解を求める方法の一つにベアストウ法がある.
f (z ) = z n + a1z n −1 + ! + an −1z + an = 0
(6.1)
2
この式を 2 次式: z + pz + q で割ると一般に,
f (z ) = (z 2 + pz + q )("###############
z n −2 + b1z n −3 + #!
+ bn −3z + bn −2 ) +
+S
"##$##%
$
# ###############
##% Rz
商
(6.2)
余り
もし余り R = S = 0 ならば f (z ) = 0 の2根が求まる.すなわち
−p ± p 2 − 4q
2
z=
(6.3)
一般に p, q の値は R, S の値に影響を与えるので R(p, q ), S (p, q ) と考える.そこで

R(p, q ) = 0




S (p, q ) = 0



(6.4)
を満たすような p, q の値を求めるアルゴリズムを作る.上式を満たす p, q は未知であるから始めに
試行値 pi , qi を与える. pi , qi の修正値を ∆p, ∆q とすると,
R(pi + ∆p, qi + ∆q ) ≅ R(pi , qi ) + Rp (pi , qi )∆p + Rq (pi , qi )∆q

S (pi + ∆p, qi + ∆q ) ≅ S (pi , qi ) + S p (pi , qi )∆p + Sq (pi , qi )∆q
ただし
∂R
,
∂p
∂S
Sp =
,
∂p
∂R
∂q
∂S
Sq =
∂q
Rp =
Rq =
ここで
R(pi + ∆p, qi + ∆q ) = 0

S (pi + ∆p, qi + ∆q ) = 0
1
(6.5)
となる ∆p, ∆q を決定する.
∆pRp (pi , qi ) + ∆qRq (pi , qi ) = −R(pi , qi )


∆pS p (pi , qi ) + ∆qSq (pi , qi ) = −S (pi , qi )


(6.6)
上式において
Rp (pi , qi ),
Rq (pi , qi ),
R(pi , qi )
S p (pi , qi ),
Sq (pi , qi ),
S (pi , qi )
を求めることができれば ∆p, ∆q は(6.6)式より求められる.

∆p = pi +1 − pi




∆q = qi +1 − qi


(6.7)
とおけば試行値の修正値 pi +1, qi +1 を得る.すなわち
pi +1 = ∆p + pi


qi +1 = ∆q + qi
(6.8)
i ← i + 1 として反復計算を行えば pi +1, qi +1 は真の値 p, q に収束する.
R(pi , qi ), S (pi , qi ) の計算:
(6.2)式を展開し(6.1)式の係数と比較すると( p → pi , q → qi とおく).

a 0 = 1 = b0




a1 = b1 + pi




a2 = b2 + pib1 + qi




&





ak = bk + pibk −1 + qibk −2




&




an −1 = R + pibn −2 + qibn−3




an = S + qibn −2




上式を b に関する式に書き換えると
2
(6.9)
b0 = 1 = a 0



b = a − p

i
1
1



b2 = a2 − pib1 − qi




&





bk = ak − pibk −1 − qibk −2




&



R = an −1 − pibn −2 − qibn −3


S = an − qibn −2



(6.10)
ここで漸化式:
bk = ak − pibk −1 − qibk −2
(b1 = a1 − pi , b0 = 1)
(6.11)
を使って k = 2 ∼ n まで繰り返すと,最後の 2 つの式は
bn −1 = an −1 − pibn −2 − qibn −3


bn = an − pibn −1 − qibn −2

(6.12)
R = an −1 − pibn −2 − qibn −3 = bn −1



S = an − qibn −2 = bn + pibn −1


(6.13)
となる.これを使うと
となり, R, S は bn と bn−1 によって計算できる.
Rp (pi , qi ), Rq (pi , qi ), S p (pi , qi ), Sq (pi , qi ) の計算
(6.13)式より
∂bn −1

Rp = ∂p
i


∂b
Rq = n −1
∂qi



∂bn
+ pi
S p =
∂pi


Sq = ∂bn + pi

∂q i
これらの偏微分係数に関する漸化式を導く.
3
∂bn −1
+ bn −1
∂pi
∂bn −1
∂qi
(6.14)

∂b
ck = k

∂pi


∂bk
dk =
∂q i

(6.15)
を定義し,(6.10)式を pi , qi でそれぞれ偏微分すれば( k = n まで),

c1 = −1



c2 = −b1 − pic1




&



c = −b − p c − q c
k −1
i k −1
i k −2
k


&




cn −1 = −bn −2 − picn −2 − qicn −3



c = −b − p c − q c


n −1
i n −1
i n −2


 n
(6.16)

d1 = 0



d = −1
2



&





dk = −bk −2 − pidk −1 − qidk −2


&





dn −1 = −bn −3 − pidn −2 − qidn −3




dn = −bn −2 − pidn −1 − qidn −2


(6.17)
Rp = cn −1




R = dn −1

 q


S p = cn + picn −1 + bn −1




S = dn + pidn −1

 q
(6.18)
∆pcn −1 + ∆qdn −1 = −bn −1



∆p(cn + picn −1 + bn −1 ) + ∆q(dn + pidn −1 ) = −bn − pibn −1


(6.19)
よって
(6.6)式は
(6.19)式の第 1 式に pi をかけ,第 2 式から引くと
4
∆pcn −1 + ∆qdn −1 = −bn −1



∆p(cn + bn −1 ) + ∆qdn = −bn


(6.20)
これより ∆p, ∆q について解くと
−bn −1 dn −1
∆p =
−bn
dn
cn −1
dn −1
cn + bn −1
dn
∆q =
,
cn −1
−bn −1
cn + bn −1
−bn
cn −1
dn −1
cn + bn −1
dn
(6.21)
この ∆p, ∆q を(6.8)式に代入すると pi , qi の修正値 pi +1, qi +1 が求められる.
以上計算アルゴリズムを整理すると,計算のステップは以下のようになる.
(1) i = 0 とし,試行値として例えば pi = 0, qi = 0 を与える.
(2)
bk = ak − pibk −1 − qibk −2 (b1 = a1 − pi , b0 = 1) を用いて k = 2 ∼ n まで繰り返し,
b2 , ! , bn −1, bn を求める.
(3)
ck = −bk −1 − pick −1 − qick −2 (c2 = −b1 − pic1, c1 = −1) を用いて k = 3 ∼ n まで繰
り返し, c3 , ! , cn −1, cn を求める.
(4)
dk = −bk −2 − pidk −1 − qidk −2 (d2 = −1, d1 = 0) を用いて k = 3 ∼ n まで繰り返し,
d3 , ! , dn −1, dn を求める.
−bn −1 dn −1
(5)
∆p =
−bn
dn
cn −1
dn −1
cn + bn −1
dn
pi +1 = ∆p + pi ,
,
∆q =
−bn −1
cn + bn −1
−bn
cn −1
dn −1
cn + bn −1
dn
qi +1 = ∆q + qi
を計算する.
(6)
cn −1
判定条件:
5
R = bn −1




S = bn + pi +1bn −1


R > ε, S > ε
−5
( ε は例えば 10
∼ 10−10 )ならば i ← i + 1 としてステップ(2)へ
もどる.
R ≤ ε, S ≤ ε ならば f (z ) は
f (z ) ≅ (z 2 + pi z + qi )(z n −2 + b1z n −3 + ! + bn −3z + bn −2 ) = 0
2
とみなして z + pi z + qi = 0 より 2 根を求める.
(7) n ← n − 2 とし, n = 1 ならば z + b1 = 0 より 1 根を求め,終了.
n = 2 ならば z 2 + b1z + b2 = 0 より 2 根をもとめ.終了.
n ≥ 3 ならば a1 ← b1, a2 ← b2 , ! , an ← bn としてステップ(1)へ
もどる.
(例 1)
f (z ) = (x − 2 + i )(x − 2 − i )(x − 3)(x − 4)(x + 5)
= x 5 − 6x 4 − 10x 3 + 142x 2 − 355x + 300 = 0
この 5 次方程式の根を求めよ.
(解)
上述のアルゴリズムに基づくC言語のプログラム例は以下のようである.
#include<math.h>
#include<stdio.h>
int main(void)
{
int i,n,k;
long double p,q,a[6],b[6],c[6],d[6],dp,dq,R,S,e,eps,
re,im,x1,x2,delta;
n=5; a[1]=-6.0; a[2]=-10.0; a[3]=142.0;
a[4]=-355.0; a[5]=300.0; eps=1.0e-10;
6
step1:
i=0; p=0; q=0;
step2:
b[0]=1.0; b[1]=a[1]-p;
for(k=2; k<=n; k++)
b[k]=a[k]-p*b[k-1]-q*b[k-2];
/*step3:*/ c[1]=-1.0; c[2]=-b[1]-p*c[1];
for(k=3; k<=n; k++)
c[k]=-b[k-1]-p*c[k-1]-q*c[k-2];
/*step4:*/ d[1]=0; d[2]=-1.0;
for(k=3; k<=n; k++)
d[k]=-b[k-2]-p*d[k-1]-q*d[k-2];
/*step5:*/ delta=c[n-1]*d[n]-d[n-1]*(c[n]+b[n-1]);
dp=(-b[n-1]*d[n]+b[n]*d[n-1])/delta;
dq=(-c[n-1]*b[n]+b[n-1]*(c[n]+b[n-1]))/delta;
p=dp+p; q=dq+q;
/*step6:*/ R=b[n-1]; S=b[n]+p*b[n-1]; e=p*p-4.0*q;
if(R*R>eps && S*S>eps){i=i+1; goto step2;}
else if(e<0){re=-0.5*p; im=0.5*sqrt(-e);
printf("%f
i %f¥n",re,im);
printf("%f
-i %f¥n",re,im);
printf("R=%e S= %e i=%d¥n", R,S,i);}
else{x1=0.5*(-p+sqrt(e)); x2=0.5*(-p-sqrt(e));
printf("%f¥n",x1); printf("%f¥n",x2);
printf("R=%e S= %e i=%d¥n", R,S,i);};
/*step7:*/ n=n-2;
if(n==1){printf("%f¥n",-b[1]); goto owari;};
if(n==2){e=b[1]*b[1]-4.0*b[2];
if(e<0){re=-0.5*p; im=0.5*sqrt(-e);
printf("%f
i %f¥n",re,im);
printf("%f -i %f¥n",re,im);
printf("R=%e S= %e i=%d¥n",R,S,i);
goto owari;}
7
else{x1=0.5*(-b[1]+sqrt(e));
x2=0.5*(-b[1]-sqrt(e));
printf("%f¥n",x1); printf("%f¥n",x2);
printf("R=%e S= %e i=%d¥n",R,S,i);
goto owari;}
};
if(n>=3){for(k=1; k<=n; k++) a[k]=b[k]; goto step1;};
owari:
return 0;
}
実行結果:
2.000000
i 1.000000
2.000000 -i 1.000000
R=-5.860450e-006 S= 8.312085e-006 i=6
4.000000
-5.000000
R=6.405685e-010 S= 3.205671e-009 i=7
3.000001
Press any key to continue
(参考)C言語の処理系は Microsoft Visual C++ 6.0 を用いた,Cを起動する方法および
コンパイルの方法等は下記の書物に出ている.
“やさしいC”
高橋麻奈著
ソフトバンク(株)
8