Bài giảng Phương pháp tính - Chương 2: Giải gần đúng phương trình đại số và siêu việt

CHƯƠNG 2: GIẢI GẦN ĐÚNG PHƯƠNG TRÌNH  
ĐẠI SỐ VÀ SIÊU VIỆT  
§1. KHÁI NIỆM CHUNG  
Nếu phương trình đại số hay siêu việt khá phức tạp thì ít khi tìm được nghiệm đúng. Bởi vậy việc  
tìm nghiệm gần đúng và ước lượng sai số rất cần thiết.  
Ta xét phương trình :  
f(x) = 0  
(1)  
với f(x) là hàm cho trước của biến x. Chúng ta cần tìm giá trị gần đúng của nghiệm của phương trình này.  
Quá trình giải thường chia làm hai bước: bước sơ bộ và bước kiện toàn nghiệm.  
Bước giải sơ bộ có 3 nhiệm vụ: vây nghiệm, tách nghiệm và thu hẹp khoảng chứa nghiệm.  
Vây nghiệm là tìm xem các nghiệm của phương trình có thể nằm trên những đoạn nào của trục x.  
Tách nghiệm là tìm các khoảng chứa nghiệm soa cho trong mỗi khoảng chỉ đúng một nghiệm. Thu hẹp  
khoảng chứa nghiệm là làm cho khoảng chứa nghiệm càng nhỏ càng tốt. Sau bước sơ bộ ta có khoảng chứa  
nghiệm đủ nhỏ.  
Bước kiện toàn nghiệm tìm các nghiệm gần đúng theo yêu cầu đặt ra.  
rất nhiều phương pháp xác định nghiệm của (1). Sau đây chúng ta xét từng phương pháp.  
§2.PHƯƠNG PHÁP LẶP ĐƠN  
Giả sử phương trình (1) được đưa về dạng tương đương :  
x = g(x)  
2)  
từ giá trị xo nào đó gọi là giá trị lặp đầu tiên ta lập dãy xấp xỉ bằng công thức:  
xn = g(x+-1)  
với n = 1,2,....  
Hàm g(x) được gọi là hàm lặp. Nếu dãy xn   khi n  thì ta nói phép lặp (3) hội tụ.  
(3)  
x1  
xo  
xo x1  
Ta có định lí: Xét phương pháp lặp (3), giả sử :  
- [a,b] là khoảng phân li nghiệm của phương trình (1) tức của (2)  
- mọi xn tính theo (3) đều thuộc [a, b]  
- g(x) có đạo hàm thoả mãn :  
g (x) q 1 ,a xb  
(4)  
trong đó q là một hằng sthì phương pháp lặp (3) hội tụ  
Ta có thể minh hoạ phép lặp trên bằng hình vẽ trên.  
Cách đưa phương trình f(x) = 0 về dạng x = g(x) được thực hiện như sau: ta thấy f(x) = 0 có thể biến  
đổi thành x = x + f(x) với   0. Sau đó đặt x+f(x) = g(x) sao cho điều kiện (4) được thoả mãn.  
dụ: xét phương trình  
x3 + x - 1000 = 0  
Sau bước giải sơ bộ ta có nghiệm x1 ( 9,10 )  
Nếu đưa phương trình về dạng:  
x = 1000 - x3 = g(x)  
thì dễ thấy | g'(x) | > 1 trong khoảng ( 9, 10 ) nên không thoả mãn điều kiện (4)  
Chúng ta đưa phương trình về dạng  
x 3 1000 x  
13  
thì ta thấy điều kiện (4) được thoả mãn.Xây dựng dãy xấp xỉ  
3
n1 1000x  
x
n
với xo chọn bất kì trong ( 9, 10 )  
Trên cơ sở phương pháp này chúng ta có các chương trình tính toán sau:  
Chương trình giải phương trình exp((1/3)*ln(1000-x)) với số lần lặp cho trước  
Chương trình 2-1  
//lap don  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
void main()  
{
int i,n;  
float x,x0;  
float f(float);  
clrscr();  
printf("Cho so lan lap n = ");  
scanf("%d",&n);  
printf("Cho gia tri ban dau cua nghiem x0 = ");  
scanf("%f",&x0);  
x=x0;  
for (i=1;i<=n;i++)  
x=f(x);  
printf("Nghiem cua phuong trinh la :%.4f",x);  
getch();  
}
float f(float x)  
{
float a=exp((1./3.)*log(1000-x));  
return(a);  
}
và chương trình giải bài toán bằng phương pháp lặp với sai số cho trước  
Chương trình 2-2  
//lap don  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
void main()  
{
int i;  
float epsi,x,x0,y;  
float f(float);  
clrscr();  
printf("Cho sai so epsilon = ");  
scanf("%f",&epsi);  
printf("Cho gia tri ban dau cua nghiem x0 = ");  
scanf("%f",&x0);  
14  
x=x0;  
y=f(x);  
if (abs(y-x)>epsi)  
{
x=y;  
y=f(x);  
}
printf("Nghiem cua phuong trinh la %.6f",y);  
getch();  
}
float f(float x)  
{
float a=exp((1./3.)*log(1000-x));  
return(a);  
}
Cho giá trị đầu xo = 1.Kết quả tính toán x = 9.966555  
§3.PHƯƠNG PHÁP CHIA ĐÔI CUNG  
Giả sử cho phương trình f(x) = 0 với f(x) liên tục  
trên đoạn [a, b] và f(a).f(b) < 0. Chia đoạn [a, b] thành 2  
phần bởi chính điểm chia (a + b)/2.  
y
1. Nếu f((a+b)/2) = 0 thì = (a+b)/2  
2. Nếu f((a + b)/2) 0 thì chọn [a,(a+b)/2] hay [(a +  
b)/2, b] mà giá trị hàm hai đầu trái dấu và kí hiệu là  
[a1,b1].Đối với [a1, b1] ta lại tiến hành như [a, b]  
Cách làm trên được tả trong chương trình sau  
dùng đtìm nghiệm của phương trình:  
x4 + 2x3 - x - 1 = 0  
b
a
b1  
x
trên đoạn [0, 1]  
Chương trình 2-3  
//chia doi cung  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
#define epsi 0.00001  
void main()  
{
float x0,x1,x2;  
float y0,y1,y2;  
float f(float);  
int maxlap,demlap;  
clrscr();  
printf("Tim nghiem cua phuong trinh phi tuyen");  
printf("\nbang cach chia doi cung\n");  
printf("Cho cac gia tri x0,x1,maxlap\n");  
printf("Cho gia tri x0 = ");  
scanf("%f",&x0);  
printf("Cho gia tri x1 = ");  
scanf("%f",&x1);  
printf("Cho so lan lap maxlap = ");  
15  
scanf("%d",&maxlap);  
y0=f(x0);  
y1=f(x1);  
if ((y0*y1)>0)  
{
printf("Nghiem khong nam trong doan x0 - x1\n");  
printf(" x0 = %.2f\n",x0);  
printf(" x1 = %.2f\n",x1);  
printf(" f(x0) = %.2f\n",y0);  
printf(" f(x1) = %.2f\n",y1);  
}
demlap=0;  
do  
{
x2=(x0+x1)/2;  
y2=f(x2);  
y0=f(x0);  
if (y0*y2>0)  
x0=x2;  
else  
x1=x2;  
demlap=demlap+1;  
}
while(((abs((y2-y0))>epsi)||(demlap<maxlap)));  
if (demlap>maxlap)  
{
printf("Phep lap khong hoi tu sau %d lan lap ",maxlap);  
printf(" x0 = %.2f\n",x0);  
printf(" x1 = %.2f\n",x1);  
printf(" f(x2) = %.2f\n",y2);  
}
else  
{
printf("Phep lap hoi tu sau %d lan lap\n",demlap);  
printf("Nghiem x = %.2f",x2);  
}
getch();  
}
float f(float x)  
{
float a=x*x*x*x+2*x*x*x-x-1 ;  
return(a);  
}
Kết quả tính cho nghiệm: x = 0.87  
§4. PHƯƠNG PHÁP DÂY CUNG  
Giả sử f(x) liên tục trên trên đoạn [a, b] và f(a).f(b) < 0. Cần tìm nghiệm của f(x) = 0. Đxác định ta  
xem f(a) < 0 và f(b) > 0. Khi đó thay vì chia đôi đoạn [a, b] ta chia [a, b] theo tỉ lệ -f(a)/f(b). Điều đó cho ta  
nghiệm gần đúng :  
x1 = a + h1  
Trong đó  
f(a)  
f(a)f(b)  
1   
h
(ba)  
16  
Tiếp theo dùng cách đó với đoạn [ a, x1] hay [x1, b] mà hai đầu hàm nhận giá trị trái dấu ta được  
nghiệm gần đúng x2 v.v.  
Về mặt hình học, phương pháp này có nghĩa kẻ dây cung của đường cong f(x) qua hai điểm A[a, f(a)] và  
B[b, f(b)]. Thật vậy phương trình dây cung AB có dạng:  
y f(a)  
b a f(b) f(a)  
Cho x = x1 y = 0 ta có  
x a  
f(a)  
f(b) f(a)  
x1 a   
(b a)  
a
x1 b  
Trên cơ sở của phương pháp ta có chương trình tính  
nghiệm của phương trình  
x4 + 2x3 - x - 1 = 0  
trên đoạn [0,1]  
Chương trình 2-4  
//phuong phap day cung  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
#define epsi 0.00001  
void main()  
{
float a,b,fa,fb,dx,x;  
float f(float);  
clrscr();  
printf("Tim nghiem cua phuong trinh phi tuyen\n");  
printf("bang phuong phap day cung\n");  
printf("Cho cac gia tri a,b\n");  
printf("Cho gia tri cua a = ");  
scanf("%f",&a);  
printf("Cho gia tri cua b = ");  
scanf("%f",&b);  
fa=f(a);  
fb=f(b);  
dx=fa*(b-a)/(fa-fb);  
while (fabs(dx)>epsi)  
{
x=a+dx;  
fa=f(x);  
if((fa*fb)<=0)  
a=x;  
else  
b=x;  
fa=f(a);  
fb=f(b);  
dx=fa*(b-a)/(fa-fb);  
}
printf("Nghiem x = %.3f",x);  
getch();  
}
17  
float f(float x)  
{
float e=x*x*x*x+2*x*x*x-x-1;  
return(e);  
}
Kết quả tính cho nghiệm: x = 0.876  
§5. PHƯƠNG PHÁP LẶP NEWTON  
Phương pháp lặp Newton (còn gọi là phương pháp tiếp tuyến) được dùng nhiều vì nó hội tụ  
nhanh. Giả sử f(x) có nghiệm đã được tách trên đoạn [a,  
b] đồng thời f'(x) và f"(x) liên tục giữ nguyên dấu trên  
đoạn [a, b]. Khi đã tìm được xấp xỉ nào đó xn [a, b] ta có  
thể kiện toàn nó theo phương pháp Newton. Từ mút B ta vẽ  
tiếp tuyến với đường cong. Phương trình đường tiếp tuyến  
là  
y f(x0 ) f (b)(x x0 )  
Tiếp tuyến này cắt trục hoành tại điểm có y = 0, nghĩa là:  
a
f(x0 ) f (b)(x1 x0 )  
x
1  
b = xo  
hay :  
f(x0 )  
x1 x0   
f (x0 )  
Từ x1 ta lại tiếp tục vẽ tiếp tuyến với đường cong thì giao điểm xi sẽ tiến tới nghiệm của phương trình.  
Việc chọn điểm ban đầu xo rất quan trọng. Trên hình vẽ trên ta thấy nếu chọn điểm ban đầu xo = a  
thì tiếp tuyến sẽ cắt trục tại một điểm nằm ngoài đoạn [a, b]. Chọn xo = b sẽ thuận lợi cho việc tính toán.  
Chúng ta có định lí:  
Nếu f(a).f(b) < 0 ; f(x) và f"(x) khác không và giữ nguyên dấu xác định khi x [a, b] thì xuất phát từ xo  
[a, b] thoả mãn điều kiện f(xo).f(xo) > 0 thể tính theo phương pháp Newton nghiệm duy nhất với đchính xác  
tuỳ ý.  
Khi dùng phương pháp Newton cần lấy xo là đầu mút của đoạn [a,b] để tại đó f(xo).f"(xo) > 0. Áp  
dụng thuyết trên chúng ta xây dựng chương trình tính sau:  
Chương trình 2-5  
//phuong phap Newton  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
#include <stdlib.h>  
#define n 50  
#define epsi 1e-5  
void main()  
{
float t,x0;  
float x[n];  
int i;  
float f(float);  
float daoham(float);  
clrscr();  
printf("Tim nghiem cua phuong trinh phi tuyen\n");  
printf("bang phuong phap lap Newton\n");  
18  
printf("Cho gia tri cua x0 = ");  
scanf("%f",&x0);  
i=1;  
x[i]=x0;  
do  
{
x[i+1] = x[i]-f(x[i])/daoham(x[i]);  
t = fabs(x[i+1]-x[i]);  
x[i]=x[i+1];  
i=i+1;  
if (i>100)  
{
printf("Bai toan khong hoi tu\n");  
getch();  
exit(1);  
}
else  
;
}
while (t>=epsi);  
printf("Nghiem x = %.5f",x[i]);  
getch();  
}
float f(float x)  
{
float a=x*x-x-2;  
return(a);  
}
float daoham(float x)  
{
float d=2*x-1;  
return(d);  
}
Chương trình này được dùng xác định nghiệm của hàm đã được định nghĩa trong function. Trong  
trường hợp này phương trình đó là:  
x2 - x - 1 = 0  
Kết quả tính với giá trị đầu xo = 0 cho nghiệm x = 2.  
§6. PHƯƠNG PHÁP MULLER  
Trong phương pháp dây cung khi tìm nghiệm trong đoạn [a, b] ta xấp xỉ hàm bằng một đường  
thẳng. Tuy nhiên để giảm lượng tính toán và để nghiệm hội tụ nhanh hơn ta có thể dùng phương pháp  
Muller. Nội dung của phương pháp này là thay hàm trong đoạn [a, b] bằng một đường cong bậc 2 mà ta  
hoàn toàn có thể tìm nghiêm chính xác của nó. Gọi các điểm đó có hoành độ lần lượt là a = x2, b = x1 và ta  
chọn thêm một điểm x0 nằm trong đoạn [x2, x1]. Gọi  
h1 = x1 - x0  
h2 = x0 - x2  
v = x - x0  
f(x0) = f0  
f(x1) = f1  
f(x2) = f2  
19  
h2  
h1  
   
Qua 3 điểm này ta có một đường parabol:  
y = av2 + bv + c  
Ta tìm các hệ số a,b,c từ các giá trị đã biết v:  
v 0(x x0 ) a(0)2 b(0) c f0  
v h1(x x1) ah12 bh1 c f1  
v h2(x x2 ) ah22 bh2 c f2  
Từ đó ta có :  
f1 f0 (1 ) f2  
a   
h12 (1 )  
f1 f0 ah12  
b   
h1  
c f0  
Sau đó ta tìm nghiệm của phương trình av2 + bv + c = 0 và có :  
2c  
n1,2 x0   
b b2 4ac  
Tiếp đó ta chọn nghiệm gần x0 nhất làm một trong 3 điểm đtính xấp xỉ mới. Các điểm này được chọn gần  
nhau nhất. Tiếp tục quá trình tính đến khi đạt đchính xác yêu cầu thì dừng lại.  
dụ: Tìm nghiệm của hàm f(x) = sin(x) - x/2 trong đoạn [1.8, 2.2]. Ta chọn x0 = 2  
Ta có : x0 = 2 f(x0) = -0.0907  
h1 = 0.2  
f(x1) = -0.2915  
f(x2) = 0.07385  
x1 = 2.2  
x2 = 1.8  
h2 = 0.2  
= 1  
Vậy thì :  
1(0.2915) (0.0907)(11) 0.07385  
10.22 (11)  
a   
b   
 0.45312  
0.2915 (0.097) (0.45312)0.22  
 0.91338  
0.2  
c  0.0907  
Ta có nghiệm gần x0 nhất là :  
2(0.0907)  
n1 2.0   
1.89526  
0.91338 (0.91338)2 4(0.45312)(0.0907)  
Với lần lặp thhai ta có :  
x0 = 1.89526  
x1 = 2.0  
x2 = 1.8  
f(x0) = 1.918410-4  
f(x1) = -0.0907  
f(x2) = 0.07385  
h1 = 0.10474  
h2 = 0.09526  
= 0.9095  
Vậy thì :  
0.9095(0.0907) (1.9184104 )1.9095 0.07385  
0.90950.104742 1.9095  
a   
 0.4728  
0.0907 1.9184104 (0.4728)0.104742  
b   
 0.81826  
0.10474  
c 1.9184104  
Ta có nghiệm gần x0 nhất là :  
20  
21.9184104  
n1 1.89526   
1.89594  
0.81826 (0.81826)2 4(0.4728)1.9184104  
Ta có thể lấy n1 = 1.895494 làm nghiệm của bài toán.  
Chương trình giải bài toán bằng phương pháp Muller như sau:  
Chương trình 2-6  
//phuong phap Muller  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
#include <stdlib.h>  
void main()  
{
float x0,x1,x2,h1,h2,eps;  
float a,b,c,gamma,n1,n2,xr;  
int dem;  
float f(float);  
clrscr();  
printf("PHUONG PHAP MULLER\n");  
printf("\n");  
printf("Cho khoang can tim nghiem [a,b]\n");  
printf("Cho gia tri duoi a = ");  
scanf("%f",&x2);  
printf("Cho gia tri tren b = ");  
scanf("%f",&x1);  
if (f(x1)*f(x2)>0)  
{
printf("\n");  
printf("Nghiem khong nam trong doan nay\n");  
getch();  
exit(1);  
}
eps=1e-5;  
x0=(x1+x2)/2;  
dem=0;  
do  
{
dem=dem+1;  
h1=x1-x0;  
h2=x0-x2;  
gamma=h2/h1;  
a=(gamma*f(x1)- f(x0)*(1+gamma)+f(x2))/(gamma*(h1*h1)*(1+gamma));  
b=(f(x1)-f(x0)-a*(h1*h1))/h1;  
c=f(x0);  
if ((a==0)&&(b!=0))  
{
n1=-c/b;  
n2=n1;  
}
if ((a!=0)&&(b==0))  
{
21  
n1=(-sqrt(-c/a));  
n2=(sqrt(-c/a));  
}
if ((a!=0)&&(b!=0))  
{
n1=x0-2*c/(b+(sqrt(b*b-4*a*c)));  
n2=x0-2*c/(b-(sqrt(b*b-4*a*c)));  
}
if (fabs(n1-x0)>fabs(n2-x0))  
xr=n2;  
else  
xr=n1;  
if (xr>x0)  
{
x2=x0;  
x0=xr;  
}
else  
{
x1=x0;  
x0=xr;  
}
}
while (fabs(f(xr))>=eps);  
printf("\n");  
printf("Phuong trinh co nghiem x = %.5f sau %d lan lap",xr,dem);  
getch();  
}
float f(float x)  
{
float a=sin(x)-x/2;  
return(a);  
}
§7. PHƯƠNG PHÁP LẶP BERNOULLI  
nhiều phương pháp đtìm nghiệm của một đa thức. Ta xét phương trình:  
aoxn + a1xn-1 +  + an = 0  
Nghiệm của phương trình trên thoả mãn định lí: Nếu max{| a1 |, | a2 |,..., |an |} = A thì các nghiệm của phương  
trình thoả mãn điều kiện | x | < 1 + A/ | a0|  
Phương pháp Bernoulli cho phép tính toán nghiệm lớn nhất của một đa thức Pn(x) có n nghiệm  
thực phân biệt. Sau khi tìm được nghiệm lớn nhất ta chia đa thức Pn(x) cho (x-) và nhận được đa thức  
mới Qn-1(x). Tiếp tục dùng phương pháp Bernoulli đtìm nghiệm lớn nhất của Qn-1(x).  
Sau đó lại tiếp tục các bước trên cho đến khi tìm hết các nghiệm của Pn(x).  
Chúng ta khảo sát phương trình sai phân dạng như sau :  
= aoyk+n + a1yk+n-1 +.....+ anyk = 0  
(1)  
Đây là một phương trình sai phân tuyến tính hệ số hằng. Khi cho trước các giá trị đầu yo, y1,..yn-1 ta tìm  
được các giá trị yn, yn+1,.. Chúng được gọi nghiệm của phương trình sai phân tuyến tính (1).  
Đa thức  
Pn(x) = a0xn + a1xn-1 +..+an-1x + an  
(2)  
với cùng một hệ số ai như (1) được gọi đa thức đặc tính của phương trình sai phân tuyến tính (1). Nếu (2)  
có n nghiệm phân biệt x1, x2,.., xn thì (1) có các nghiệm riêng là  
yi xik  
Nếu yi là các nghiệm của phương trình sai phân tuyến tính (1),thì  
22  
yk c1x1k c2xk2   cnxnk  
với các hệ số ci bất cũng nghiệm của phương trình sai phân tuyến tính hệ số hằng (1).  
Nếu các nghiệm cần sao cho :  
(3)  
| x1| | x2 | ...| xn|  
k  
c x  
c2 x1  
1 2   
Vậy  
y c xk 1  
  
1   
k
1
k1  
c x  
và  
yk1 c1x1k1 1  
  
1 2   
c2 x1  
k1  
c x  
c2 x1  
1 2   
1  
  
do đó : yk1  
x1  
k  
yk  
c x  
1 2   
1  
  
c2 x1  
do  
x1 > x2 >...> xn  
k  k1  
x
x1  
x
x1  
2   2   
nên:  
,
0 khi k    
   
   
yk1  
vậy:  
0 khi k    
yk  
Nghĩa là :  
yk1  
x1  
yk  
lim  
k  
Nếu phương trình vi phân gồm n+1 hệ số, một nghiệm riêng yk thể được xác định từ n giá trị yk-  
1, yk-2,...,yn-1. Điều cho phép tính toán bằng cách  
truy hồi các nghiệm riêng của phương trình vi phân.  
Đtính nghiệm lớn nhất của đa thức, ta xuất phát từ các nghiệm riêng y1 = 0, y1 = 0,.., yn =1 đtính  
yn+1. Cách tính này được tiếp tục đtính yn+2 xuất phát từ y1 = 0, y2 = 0,..,yn+1 tiếp tục cho đến khi yk+1/yk  
không biến đổi nữa. Trị số của yk+n được tính theo công thức truy hồi :  
1
a0  
ykn    
a1ykn1   an yk  
(4)  
dụ: Tính nghiệm của đa thức Pn(x) = P3(x) = x3 - 10x2 + 31x - 30.  
Như vậy ao = 1, a1 = -10,a2 = 31 và a3 = -30.  
Phương trình sai phân tương ứng là :  
yk+3 -10yk+2 + 31yk+1 - 30yk = 0  
Ta cho trước các giá trị y1 = 0; y2 = 0 và y3 = 1. Theo (4) ta tính được :  
y4 = - (-10y3 + 31y2 - 30y1) = 10  
y5 = - (-10y4 + 31y3 - 30y2) = 69  
y6 = - (-10y5 + 31y5 - 30y3) = 410  
y7 = - (-10y6 + 31y5 - 30y4) = 2261  
y8 = - (-10y7 + 31y6 - 30y5) = 11970  
y9 = - (-10y8 + 31y7 - 30y6) = 61909  
y10 = - (-10y9 + 31y8 - 30y8) = 315850  
y11 = - (-10y10 + 31y9 - 30y8) = 1598421  
y12 = - (-10y11 + 31y10 - 30y9) = 8050130  
y13 = - (-10y12 + 31y11 - 30y10) = 40425749  
y14 = - (-10y13 + 31y12 - 30y11) = 202656090  
23  
y15 = - (-10y14 + 31y13 - 30y12) = 1014866581  
y16 = - (-10y15 + 31y14 - 30y13) = 5079099490  
y17 = - (-10y16 + 31y15 - 30y14) = 24409813589  
y18 = - (-10y17 + 31y16 - 30y15) = 127092049130  
y19 = - (-10y18 + 31y17 - 30y16) = 635589254740  
Tỉ số các số yk+1/yk lập thành dãy :  
10 ; 6.9 ; 5.942 ; 5.5146 ; 5.2941 ; 5.172 ; 5.1018 ; 5.0607 ; 5.0363 ; 5.0218 ; 5.013 ; 5.0078 ; 5.0047 ; 5.0028  
; 5.0017 ; 5.001  
nghĩa là chúng sẽ hội tụ tới nghiệm lớn nhất là 5 của đa thức.  
Chương trình 2-7  
//phuong phap Bernoulli  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
#include <stdlib.h>  
#define max 50  
void main()  
{
float a[max],y[max];  
int k,j,i,n,l;  
float s,e1,e2,x0,x1,x;  
clrscr();  
printf("Cho bac cua da thuc can tim nghiem n = ");  
scanf("%d",&n);  
e1=1e-5;  
printf("Cho cac he so cua da thuc can tim nghiem\n");  
for (i=0;i<=n;i++)  
{
printf("a[%d] = ",i);  
scanf("%f",&a[i]);  
}
for (k=0;k<=n;k++)  
a[k]=a[k]/a[0];  
tt: x1=0;  
for (k=2;k<=n;k++)  
y[k]=0;  
y[1]=1;  
l=0;  
do  
{
l=l+1;  
s=0;  
for (k=1;k<=n;k++)  
s=s+y[k]*a[k];  
y[0]=-s;  
x=y[0]/y[1];  
e2=fabs(x1 - x);  
x1=x;  
for (k=n;k>=1;k--)  
y[k]=y[k-1];  
}
24  
while((l<=50)||(e2>=e1));  
if(e2>=e1)  
{
printf("Khong hoi tu");  
getch();  
exit(1);  
}
else  
printf("Nghiem x = %.4f\n",x);  
n=n-1;  
if (n!=0)  
{
a[1]=a[1]+x;  
for (k=2;k<=n;k++)  
a[k]=a[k]+x*a[k-1];  
goto tt;  
}
getch();  
}
Kết quả nghiệm của đa thức x3 - 10x2 + 31x - 30 là:5 ; 3 và 2  
§8. PHƯƠNG PHÁP LẶP BIRGE - VIETTE  
Các nghiệm thực, đơn giản của một đa thức Pn(x) được tính toán khi sử dụng phương pháp Newton  
Pn (xi )  
xi1 xi   
(1)  
Pn (xi )  
Để bắt đầu tính toán cần chọn một giá trị ban đầu xo. Chúng ta có thể chọn một giá trị xo nào đó, ví  
dụ :  
an  
x0    
an1  
và tính tiếp các giá trị sau :  
Pn (x0 )  
x1 x0   
x2 x1   
Pn (x0 )  
Pn (x1 )  
Pn (x1 )  
Tiếp theo có thể đánh giá Pn(xi) theo thuật toán Horner :  
P0 = a0  
P1 = P0xi + a1  
(2)  
P2 = P1xi + a2  
P3 = P2xi + a3  
..................  
P(xi) = Pn = Pn-1xi + an  
Mặt khác khi chia đa thức Pn(x) cho một nhị thức (x - xi) ta được :  
Pn(x) = (x - xi)Pn-1(x) + bn  
(3)  
(4)  
với bn = Pn(xi). Đa thức Pn-1(x) có dạng:  
Pn-1(x) = boxn-1 + b1xn-2 + p3xn-3 +..+ bn-2x + bn-1  
Đxác định các hệ số của đa thức (4) ta thay (4) vào (3) và cân bằng các hệ số với đa thức cần tìm  
nghiệm Pn(x) mà các hệ số ai đã cho:  
(x - xi)( boxn-1 + b1xn-2+b3xn-3 +..+ bn-2x + bn-1 ) + bn  
= aoxn + a1xn-1 + a2xn-2 +...+ an x + a=  
(5)  
-1  
Từ (5) rút ra :  
25  
bo = ao  
b1 = a1 + boxi  
b2 = a2 + b1xi  
......  
(6)  
bk = ak + bk-1xi  
.......  
bn = an + bn-1xi = Pn(xi)  
Đạo hàm (3) ta được :  
Pn(x) (x xi )Pn1(x) Pn1(x)  
và:  
Pn(xi ) Pn1(xi )  
(7)  
Như vậy với một giá trị xi nào đó theo (2) ta tính được Pn(xi) và kết hợp (6) với (7) tính được Pn(xi).  
Thay các kết quả này vào (1) ta tính được giá trị xi+1. Quá trình được tiếp tục cho đến khi | xi+1 - xi | < hay  
Pn(xi+1) 0 nên 1 xi+1 một nghiệm của đa thức.  
Phép chia Pn(x) cho (x - 1) cho ta Pn-1(x) và một nghiệm mới khác được tìm theo cách trên khi  
chọn một giá trị xo mới hay chọn chính xo=1. Khi bậc của đa thức giảm xuống còn bằng 2 ta dùng các công  
thức tìm nghiệm của tam thức đtìm các nghiệm còn lại.  
dụ: Tìm nghiệm của đa thức P3(x) = x3 - x2 -16x + 24  
ao = 1  
a1 = -1  
a2= -16  
a3 = 24  
Chọn xo = 3.5 ta có :  
Po = ao = 1  
P1 = a1 + pox0 = -1 + 3.5*1 = 2.5  
P2 = a2 + p1x0 = -16 + 3.5*2.5 = -7.25  
P3 = a3 + p2x0 = 24 + 3.5*(-7.25) = - 1.375  
b0 = a0 = 1;  
b1 = a1 + box0 = -1 + 3.5*1 = 2.5  
b2 = a2 + b1x0 = -16 + 3.5*2.5 = -7.25  
P2(3.5) = b0x2 + b1x + b2 = 13.75  
Pn(x0 )  
1.375  
13.75  
x1 x0   
3.5   
3.6  
Pn(x0 )  
Lặp lại bước tính trên cho x1 ta có:  
Po = ao = 1  
P1 = a1 + pox1 = -1 + 3.6*1 = 2.6  
P2 = a2 + p1x1 = -16 + 3.6*2.6 = -6.64  
P3 = a3 + p2x1 = 24 + 3.6*(-6.64) = - 0.096  
bo = ao = 1  
b1 = a1 + box1 = -1 + 3.6*1 = 2.6  
b2 = a2 + p1x1 = -16 + 3.6*2.6 = -6.64  
P2(3.6) = b0x2 + b1x + b2 = 15.68  
Pn(x1)  
0.096  
15.68  
x2 x1   
3.6   
3.606  
Pn(x1)  
Quá trình cứ thế tiếp tục cho đến khi sai số chấp nhận được. Chương trình dưới đây mô tả thuật tính trên.  
Chương trình 2-8  
//phuong phap Birge-Viette  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
#define max 20  
void main()  
{
float a[max],p[max],d[max],x[max];  
26  
int k,j,i,n;  
float e1,e2,x0,x1;  
clrscr();  
printf("Cho bac cua da thuc n = ");  
scanf("%d",&n);  
e1=0.0001;  
printf("Cho cac he so cua da thuc can tim nghiem\n");  
for (i=0;i<=n;i++)  
{
printf("a[%d] = ",i);  
scanf("%f",&a[i]);  
}
x0=a[0];  
for (i=0;i<=n;i++)  
a[i]=a[i]/x0;  
printf("Nghiem cua phuong trinh : \n");  
tt:x0=-a[n]/a[n-1];  
j=0;  
do  
{
j=j+1;  
p[1]=x0+a[1];  
d[1]=1.0;  
for (k=2;k<=n;k++)  
{
p[k]=p[k-1]*x0+a[k];  
d[k]=d[k-1]*x0+p[k-1];  
}
x1=x0-p[n]/d[n];  
e2=fabs(x1-x0);  
if (e2>e1)  
x0=x1;  
}
while((j<=50)||(e2>=e1));  
if (e2>=e1)  
printf("Khong hoi tu");  
else  
printf(" x = %.4f\n",x1);  
n=n-1;  
if (n!=0)  
{
for (k=1;k<=n;k++)  
a[k]=p[k];  
goto tt;  
}
getch();  
}
Dùng chương trình trên đtìm nghiệm của đa thức x4 + 2x3 - 13x2 - 14x + 24 ta được các nghiệm là:-4  
; 3 ; -2 và 1.  
§9. PHƯƠNG PHÁP NGOẠI SUY AITKEN  
Xét phương pháp lặp :  
x = f(x)  
với f(x) thoả mãn điều kiện hội tụ của phép lặp, nghĩa với mọi x[a, b] ta có:  
(1)  
27  
| f’(x) | q < 1  
Như vậy :  
(2)  
(6)  
xn+1 = f(xn)  
xn = f(xn-1)  
(3)  
(4)  
Trừ (3) cho (4) và áp dụng định lí Lagrange cho vế phải với c [a, b] ta có :  
xn+1- xn = f(xn) - f(xn-1) = (xn - xn-1)f’(c)  
Vì phép lặp (1) nên :  
(5)  
| xn+1- xn | q | xn - xn-1  
= an - pb-2  
|
Chúng ta nhận thấy rằng được tính toán xuất phát từ cùng một công thức truy hồi như các hệ số  
bk và tương ứng với hệ sbn-1  
bn-1 = an-1 + sbn-2 - pbn-3 =   
Hệ số bn là :  
bn = an + sbn-1 - pbn-2 = sbn-1 +   
cuối cùng :  
R1(x) = x + = b+-1(x - s) + bn  
Ngoài ra các hệ số bi phụ thuộc vào s và p và bây giờ chúng ta cần phải tìm các giá trị đặc biệt s*  
và p* đcho bn-1 và bn triệt tiêu. Khi đó r1(x)= 0 và nghiệm của tam thức x2 - s*x + p*x sẽ nghiệm của đa  
thức Pn(x). Ta biết rằng bn-1 và bn là hàm của s và p :  
bn-1 = f(s, p)  
bn = g(s, p)  
Việc tìm s* và p* đưa đến việc giải hệ phương trình phi tuyến:  
f(s,p)0  
g(s,p)0  
Phương trình này có thể giải dễ dàng nhờ phương pháp Newton. Thật vậy với một phương trình phi tuyến  
ta có công thức lặp:  
xi+1 = xi - f(xi)/f'(xi)  
f'(xi)(xi+1 - xi) = -f(xi)  
hay  
Với một hệ có hai phương trình,công thức lặp trở thành:  
J(Xi)(Xi+1 - Xi) = -F(Xi)  
với  
Xi = { si, pi}T và Xi+1 = { si+1, pi+1}T  
f(s ,p )  
g(si ,pi )  
f f  
s p  
g g  
s p  
i
i
F(Xi )   
J(Xi )   
Quan hệ : J(Xi)X = -F(Xi) với X = {si+1 - si,pi+1 - pi}T tương ứng với một hệ phương trình tuyến tính hai ẩn số  
s = si+1 - si p = pi+1 - pi :  
f  
f  
s   
s   
p  f(si ,pi )  
p  g(si ,pi )  
s  
g  
s  
p  
g  
p  
Theo công thức Cramer ta có :  
g  
p p  
f  
f g  
s  
28  
g  
s s  
f  
g f  
p  
g  
g  
f  
f  
  
s p p s  
g g  
f f  
Đdùng được công thức này ta cần tính được các đạo hàm  
s , p , s , p . Các đạo hàm này được tính  
theo công thức truy hồi.  
Do bo = ao nên  
b0  
s  
b0  
p  
0  
0  
0  
b1 = a1 + sbo nên  
b1  
s  
b1  
p  
b0  
b2 = a2 + sb1- pbo nên  
(pb0 )  
s  
b2 a2 (sb1 )  
s  
s  
s  
Mặt khác :  
(pb0 )  
0  
a2  
(sb1 )  
s  
(b1 )  
s  
0  
s  
b1  
s  
s  
b2  
nên:  
b1 sb0  
s  
b3 = a3 + sb2- pb1 nên:  
b3  
b2  
s  
b1  
s  
b2 s  
p  
s  
Nếu chúng ta đặt :  
bk  
s  
ck1  
thì :  
co = bo  
(2)  
c1 = b1 + sbo = b1 + sco  
c2 = b2 + sc1 - pco  
....................  
ck = bk + sck-1 - pck-2  
cn-1 = bn-1 + scn-2 - pcn-3  
Như vậy các hệ số cũng được tính theo cách như các hệ số bk. Cuối cùng với f = bn-1 và g = bn ta được:  
f  
s  
f  
s  
f  
s  
f  
s  
cn2  
cn3  
cn1  
cn2  
bn1cn2 bncn3  
cn1cn3 c2n2  
s   
p   
(3)  
(4)  
bn1cn1 bncn2  
cn1cn3 c2n2  
29  
Sau khi phân tích xong Pn(x) ta tiếp tục phân tích Pn-2(x) theo phương pháp trên. Các bước tính  
toán gồm:  
- Chọn các giá trị ban đầu bất kì s0 và p0  
- Tính các giá trị bo,..,bn theo (1)  
- Tính các giá trị co,...,cn theo (2)  
- Tính so po theo (3) và (4)  
- Tính s1 = s0 + so và p1 = po+ po  
- Lặp lại bước 1 cho đến khi pi+1 = pi = p và si+1 = si = s  
- Giải phương trình x2 - sx + p đtìm 2 nghiệm của đa thức  
- Bắt đầu quá trình trên cho đa thức Pn-2(x)  
dụ: Tìm nghiệm của đa thức P4(x) = x4 - 1.1x3 + 2.3x2 + 0.5x2 + 3.3.  
Với lần lặp ban đầu ta chọn s = -1 và p =1, nghĩa là tam thức dạng: x2+x+1  
a0  
1
a1  
-1.1  
-1  
a2  
a3  
a4  
2.3  
2.1  
-1  
0.5  
-3.4  
2.1  
3.3  
0.8  
-3.4  
sbi  
-pbi-1  
bi 1  
sbi  
-2.1  
3.4  
-0.8 = bn-1  
0.7=bn  
-1.0  
-3.1  
3.1  
-5.5  
-pbi-1  
ci  
-1.0  
5.5  
3.1  
-3.2  
1
0.8 3.1  
0.7 5.5  
5.5 3.1  
3.2 5.5  
5.5 0.8  
s   
0.11  
0.06  
3.2 0.7  
5.5 3.1  
3.2 5.5  
p   
s* = -1 + 0.11 = -0.89  
p* = 1 + 0.06 = 1.06  
Tiếp tục lặp lần 2 với s1 = s* và p1 = p* ta có :  
a0  
1
a1  
-1.1  
-0.89  
a2  
2.3  
1.77  
-1.06  
a3  
0.5  
-2.68  
2.11  
a4  
3.3  
0.06  
-3.17  
sbi  
-pbi-1  
bi 1  
sbi  
-pbi-1  
ci  
-1.99  
3.01  
-1.0  
-0.07 = bn-1  
0.17=bn  
-0.89  
-2.88  
2.56  
4.51  
-4.01  
-1.03  
3.1  
1
0.07 2.88  
0.7 5.5  
4.51 2.88  
s   
 0.01  
1.03 4.51  
30  
4.51  
0.07  
1.03 0.17  
4.51 2.88  
1.03 4.51  
p   
0.04  
s* = -0.89 - 0.01 = -0.9  
p* = 1.06 + 0.04 = 1.1  
Như vậy:  
P4(x) = (x2 + 0.9x + 1.1)(x2 + 2x + 3)  
Chương trình sau áp dụng thuyết vừa nêu đtìm nghiệm của đa thức.  
Chương trình 2-10  
//phuong phap Bairstow  
#include <conio.h>  
#include <stdio.h>  
#include <math.h>  
#include <stdlib.h>  
#define m 10  
void main()  
{
float a[m],b[m],c[m];  
int i,n,v;  
float s,e1,t,p,q,r,p1,q1;  
clrscr();  
printf("Cho bac cua da thuc n = ");  
scanf("%d",&n);  
printf("Cho cac he so cua da thuc can tim nghiem\n");  
for (i=n;i>=0;i--)  
{
printf("a[%d] = ",n-i);  
scanf("%f",&a[i]);  
}
printf("\n");  
e1=0.0001;  
if (n<=2)  
if (n==1)  
{
printf("Nghiem cua he\n");  
printf("%.8f",(a[0]/(-a[1])));  
getch();  
exit(1);  
}
do  
{
v=0;  
p=1;  
q=-1;  
b[n]=a[n];  
c[n]=a[n];  
do  
{
31  
b[n-1]=b[n]*p+a[n-1];  
c[n-1]=b[n-1]+b[n]*p;  
for (i=n-2;i>=0;i--)  
{
b[i]=b[i+2]*q+b[i+1]*p+a[i];  
c[i]=c[i+2]*q+c[i+1]*p+b[i];  
}
r=c[2]*c[2]-c[1]*c[3];  
p1=p-(b[1]*c[2]-b[0]*c[3])/r;  
q1=q-(b[0]*c[2]-b[1]*c[1])/r;  
if ((fabs(b[0])<e1)&&(fabs(b[1])<e1))  
goto tt;  
v=v+1;  
p=p1;  
q=q1;  
}
while (v<=40);  
if(v>40)  
{
printf("Khong hoi tu sau 40 lan lap");  
getch();  
exit(1);  
}
tt:s=p1/2;  
t=p1*p1+4*q1;  
if(t<0)  
{
printf("Nghiem phuc\n");  
printf("%.8f+%.8fj\n",s,(sqrt(-t)/2));  
printf("%.8f-%.8fj\n",s,(sqrt(-t)/2));  
printf("\n");  
}
else  
{
printf("Nghiem thuc\n");  
printf("%.8f\n",(s+sqrt(t)/2));  
printf("%.8f\n",(s-sqrt(t)/2));  
printf("\n");  
}
for (i=2;i<=n;i++)  
a[i-2]=b[i];  
n=n-2;  
}
while ((n>2)&(r!=0.0));  
s=-a[1]/(2*a[2]);  
t=a[1]*a[1]-4*a[2]*a[0];  
if (t<0)  
{
printf("Nghiem phuc\n");  
printf("%.8f+%.8fj\n",s,(sqrt(-t)/(2*a[2])));  
printf("%.8f-%.8fj\n",s,(sqrt(-t)/(2*a[2])));  
printf("\n");  
}
else  
{
32  
Tải về để xem bản đầy đủ
doc 24 trang yennguyen 13/04/2022 6320
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Phương pháp tính - Chương 2: Giải gần đúng phương trình đại số và siêu việt", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • docbai_giang_phuong_phap_tinh_chuong_2_giai_gan_dung_phuong_tri.doc