matlab中方程根的近似计算要点.docx
《matlab中方程根的近似计算要点.docx》由会员分享,可在线阅读,更多相关《matlab中方程根的近似计算要点.docx(13页珍藏版)》请在冰豆网上搜索。
matlab中方程根的近似计算要点
实验一方程根的近似计算
一、问题
求非线性方程的根
二、实验目的
1、学会使用matlab中内部函数roots、solve、fsolve、fzero求解方程,并用之解决实际问题。
4、熟悉Matlab的编程思路,尤其是函数式M文件的编写方法。
三、预备知识
方程求根是初等数学的重要内容之一,也是科学和工程中经常碰到的数值计算问题。
它的一般形式是求方程f(x)=0的根。
如果有x*使得f(x*)=0,则称x*为f(x)=0的根,或函数f(x)的零点。
并非所有的方程都能求出精确解或解析解。
理论上已经证明,用代数方法可以求出不超过3次的代数方程的解析解,但对于次数大于等于5的代数方程,没有代数求根方法,即它的根不能用方程系数的解析式表示。
至于超越方程,通常很难求出其解析解。
不存在解析解的方程就需要结合具体方程(函数)的性质,使用作图法或数值法求出近似解。
而计算机的发展和普及又为这些方法提供了广阔的发展前景,使之成为科学和工程中最实用的方法之一。
下面介绍几种常见的求近似根的方法。
1.求方程近似解的简单方法
1.1图形方法—放大法求根
图形的方法是分析方程根的性态最简洁的方法。
不过,不要总是想得到根的精确值。
这些值虽然粗糙但直观,多少个根,在何范围,一目了然。
并且还可以借助图形局部放大功能,将根定位得更加准确一些。
例1.1求方程x5+2x2+4=0的所有根及其大致分布范围。
解
(1)画出函数f(x)=x5+2x2+4的图形,确定方程的实数根的大致范围。
为此,在matlab命令窗中输入
clf
ezplotx-x,
gridon
holdon
ezplot('x^5+2*x^2+4',[-2*pi,2*pi])
1-1函数f(x)=x5+2x2+4的图形
clf
x=-2*pi:
0.1:
2*pi;
y1=zeros(size(x));
y2=x.^5+2*x.^2+4;
plot(x,y1,x,y2)
gridon
axistight
title('x^5+2x^2+4')
xlabel('x')
从图1-1可见,它有一个实数根,大致分布在-2与2之间。
(2)将作图范围不断缩小,用放大法可得到精度越来越高的根的近似值。
在matlab命令窗中先后键入
subplot(2,2,1)
ezplotx-x,gridon,holdon,ezplot('x^5+2*x^2+4',[-2,2])
subplot(2,2,2)
ezplotx-x,gridon,holdon,ezplot('x^5+2*x^2+4',[-2,-1])
subplot(2,2,3)
ezplotx-x,gridon,holdon,ezplot('x^5+2*x^2+4',[-1.6,-1.5])
subplot(2,2,4)
ezplotx-x,gridon,holdon,ezplot('x^5+2*x^2+4',[-1.55,-1.54])
图1-2放大法求函数f(x)=x5+2x2+4的根
由图1-2可知,方程的根在-1.545与-1.54之间。
1.2数值方法
非线性方程f(x)=0求根的方法有区间法和迭代法两大类,二分法、弦位法是区间法,简单迭代法和牛顿迭代法及其变形是迭代法,这里只给出二分法、简单迭代法和牛顿迭代法的构造过程。
(1)根的隔离与二分法
根的隔离思想来源于连续函数的零点定理:
若函数f(x)在闭区间[a,b]上连续,且f(a)f(b)<0,则方程f(x)=0在(a,b)内至少有一根x*。
二分法是最简单的求根方法,它是利用连续函数的零点定理,将含根区间逐次减半缩小,取区间的中点构造收敛点列{xn}来逼近根x*。
用该方法求f(x)=0的近似解可分两步做:
第一步,确定根的近似位置或大致范围,即确定一个区间[a,b],使所求根是位于这个区间内的唯一实根。
这个区间称为根的隔离区间,这可以通过函数作图达到:
先画出y=f(x)的图形,然后从图上定出它与x轴交点的大概位置。
第二步,以根的隔离区间[a,b]的端点作为根的初始近似值,用二分法逐步改进根的近似值的精确度,直至求得满足精确度的近似解。
具体步骤如下:
取[a,b]的中点x0=(a+b)/2,若f(x0)=0,则x0就是f(x)=0的根x*。
若f(a)f(x0)<0,则根x*必在区间(a,x0)内,取a1=a,b1=x0;否则根x*必在区间(x0,b)内,取a1=x0,b1=b。
这样,得到新区间[a1,b1],其长度为[a,b]的一半。
如此继续下去,进行n等分后,得到一组不断缩小的区间序列[a,b],[a1,b1],[a2,b2],…,[an,bn],…,和对应区间的中点数列xn=(an+bn)/2,n=0,1,2,…,其中每个区间都含有根x*,满足
[a,b]
[a1,b1]
[a2,b2]
…
[an,bn]
…
且每个区间的长度都是前一区间长度的一半。
由于[an,bn]的长度为(b-a)/2n,当n不断变大时,这些区间将收敛于一点x*,该点即为所求的根。
当做到第n步时,有
选择适当的步数n,就可达到满意的精度。
用二分法,理论上区间中点序列{xn}将收敛到根的真值,但收敛速度较慢,所以通常用二分法为其他方法提供初步的近似值。
(2)简单迭代法
迭代法的基本原理是构造一个迭代公式,反复用它得出一个逐次逼近方程根的数列,数列中每一项都是方程根的近似值,只是精度不同。
简单迭代法也成逐次迭代法,是非线性方程求根中各类迭代法的基础。
由于对方程作等价变换根不发生变换,将方程f(x)=0等价变换为
,构造迭代计算公式
。
取定初值x0,算出数列{xn}。
如果{xn}收敛于x*,则有
这说明,x*就是方程f(x)=0的根。
上面
称为不动点方程,
称为迭代函数,数列{xn}称为迭代数列。
(3)牛顿迭代法
如果f(x)在[a,b]上具有二阶导数,f(a)f(b)<0,且f'(x)与f''(x)在[a,b]上保持同号,这时可采用牛顿迭代法求方程f(x)=0在(a,b)内的惟一实根。
牛顿迭代法将非线性方程线性化处理为近似方程,然后用近似方程获得求根的迭代公式。
具体做法如下:
设xn是f(x)=0的一个近似根,把f(x)在xk处作泰勒展开,得
f(x)=f(xk)+f'(xk)(x-xk)+(f''(xk)/2!
)(x-xk)2+…
取前两项来近似代替f(x),则得近似线性方程
f(x)≈f(xk)+f'(xk)(x-xk)=0
如果f'(xk)≠0,令其解为xk+1,得
xk+1=xk-f(xk)/f'(xk),k=1,2,..(1-1)
上式称为f(x)=0的根的牛顿迭代格式。
牛顿法具有明显的几何意义,方程
y=f(xk)+f'(xk)(x-xk)
是曲线在点(xk,f(xk))处的切线方程。
迭代方程(1.1)就是切线与x轴交点的横坐标,所以牛顿迭代法就是用切线与x轴交点的横坐标近似替代曲线与x轴交点的横坐标。
因此牛顿法也称切线法,是非线性方程求根方法中收敛最快的方法。
2.matlab中方程求解的基本命令
roots(p):
求多项式方程的根,其中p是多项式系数按降幂排列所形成的向量。
solve(fun):
求方程fun=0的符号解,如果不能求得精确的符号解,可以计算可变精度的数值解。
solve(fun,var):
对指定变量var求代数方程fun=0的符号解。
fsolve(fun,x0):
用最小二乘法求非线性方程fun=0在估计值x0附近的近似解。
fzero(fun,x0):
求函数fun在x0附近的零点。
四、实验过程
1、编写二分法求根程序,求方程x3+1.1x2+0.9x-1.4=0实根的近似值,使误差不超过10-3。
解:
(1)求根的初始隔离区间
在matlab工作区输入命令:
ezplotx-x,gridon,holdon,ezplot('x^3+1.1*x^2+0.9*x-1.4')
图1-4
画出曲线图1-4。
由上图可知,根应在-2和2之间,进一步画出该部分的图形。
ezplotx-x,gridon,holdon,ezplot('x^3+1.1*x^2+0.9*x-1.4',[-2,2])
图1-5
由图1-5可见,根在0.5与1之间。
(2)编写程序如下:
f=input('输入函数:
f(x)=');
qujian=input('输入区间=');
err=input('输入误差=');
a=qujian
(1);
b=qujian
(2);
yc=1;
while((b-a)>err)&(yc~=0)
c=(a+b)/2;
x=a;ya=eval(f);
x=b;yb=eval(f);
x=c;yc=eval(f);
ifya*yc<0
b=c;
else
a=c;
end
x0=c
end
存为文件erfenfa.m
调用erfenfa得到如下结果:
>>erfenfa
输入函数:
f(x)='x^3+1.1*x^2+0.9*x-1.4'
输入区间=[0,1]
输入误差=0.001
x0=0.5000
x0=0.7500
x0=0.6250
x0=0.6875
x0=0.6563
x0=0.6719
x0=0.6641
x0=0.6680
x0=0.6699
x0=0.6709
由此得到,方程的根的近似值为0.6709.
2、编写牛顿迭代法求根程序,求1中方程x3+1.1x2+0.9x-1.4=0的实根的近似值,并计算迭代次数为6的近似根。
解:
由1可知,[0.5,1]是根所在的区间,在[0.5,1]上
f(x)=x3+1.1x2+0.9x-1.4
f'(x)=3*x2+2.2x+0.9,f''(x)=6x+2.2
f'(x)与f''(x)在[0.5,1]上保持同号,f
(1)>0与f''
(1)同号,所以取x0=1为迭代初始值。
用matlab语言编写一般的程序如下:
f=input('输入函数:
f(x)=');
n=input('请输入迭代次数:
n=');
x0=input('请输入迭代初始值:
x0=');
f1=diff(f);
formatlong
fori=1:
n
x=x0;
fx0=eval(f);
f1x0=eval(f1);
x0=x0-fx0/f1x0;
fprintf('x0=%12.10f\n',x0)
end
存为文件niudunfa.m,调用及运行结果如下:
>>niudunfa
输入函数:
f(x)='x^3+1.1*x^2+0.9*x-1.4'
请输入迭代次数:
n=6
请输入迭代初始值:
x0=1
x0=0.7377049180
x0=0.6741688117
x0=0.6706675756
x0=0.6706573108
x0=0.6706573107
x0=0.6706573107
由此得到,方程的根的近似值为0.6706573107。
3.用matlab中的内部函数求方程的根。
(1)用roots求方程x9+x8+1=0的根;
(2)用solve求上述方程的根;
(3)用fzero求方程x2+4sinx=25的实根;
(4)用fsolve求方程x=e-x在0附近的根;
解:
(1)在matlab命令窗口输入命令:
p=zeros(10,1);
p([1:
2,end],1)=1;
roots(p)
ans=
-1.213149723059643
-0.901727735578254+0.575312094072893i
-0.901727735578254-0.575312094072893i
-0.269351937596575+0.940578401023146i
-0.269351937596575-0.940578401023146i
0.416834006536573+0.841919773084660i
0.416834006536573-0.841919773084660i
0.860820528168075+0.334352258897906i
0.860820528168075-0.334352258897906i
(2)在matlab命令窗口输入命令:
solve('x^9+x^8+1=0')
ans=
RootOf(X1^9+X1^8+1,X1)
(3)首先作图确定根的大致范围:
clf,ezplotx-x,gridon,holdon,ezplot('x^2+4*sin(x)-25')
图1-6
由图1-6可确定两根在x1≈-4,x2≈5附近。
再具体求根。
x1=fzero('x^2+4*sin(x)-25',-4)
x2=fzero('x^2+4*sin(x)-25',5)
x1=
-4.586052690568049
x2=
5.318580248846235
(4)在matlab命令窗口输入命令:
x=fsolve('x-exp(-x)',0)
Optimizationterminated:
first-orderoptimalityislessthanoptions.TolFun.
x=
0.567143165036970
五、实验练习
1、用二分法求方程x3-1.2x+6=0的实根的近似值,使误差不超过10-3,并用roots命令进行检验。
2、用牛顿迭代法求方程x3-1.1x2+2x-8=0的实根的近似值,使误差不超过0.001,并用solve命令进行检验。
3、用简单迭代法求方程x=e-x在0附近的根,并用fsolve命令进行检验。