数值计算二分法简单迭代法Newton迭代法弦截法割线法双点弦法.docx
《数值计算二分法简单迭代法Newton迭代法弦截法割线法双点弦法.docx》由会员分享,可在线阅读,更多相关《数值计算二分法简单迭代法Newton迭代法弦截法割线法双点弦法.docx(18页珍藏版)》请在冰豆网上搜索。
数值计算二分法简单迭代法Newton迭代法弦截法割线法双点弦法
本科生实验报告
实验课程数值计算方法
学院名称信息科学与技术学院
专业名称计算机科学与技术
学生姓名
学生学号
指导教师
实验地点
实验成绩
二〇一六年五月二〇一六年五月
实验一非线性方程求根
问题描述
实验目的:
掌握非线性方程求根的基本步骤及方法,。
实验内容:
试分别用二分法、简单迭代法、Newton迭代法、弦截法(割线法、双点弦法),求x5-3x3+x-1=0在区间[-8,8]上的全部实根,误差限为10-6。
要求:
讨论求解的全过程,对所用算法的局部收敛性,优缺点等作分析及比较,
第2章算法思想
二分法
思想:
在函数的单调有根区间内,将有根区间不断的二分,寻找方程的解。
步骤:
1.取中点mid=(x0+x1)/2
2.若f(mid)=0,则mid为方程的根,否则比较与两端的符号,若与f(x0)
异号,则根在[x0,mid]之间,否则在[mid,x1]之间。
3并重复上述步骤,直达达到精度要求,则mid为方程的近似解。
简单迭代法
思想:
迭代法是一种逐次逼近的方法,它是固定公式反复校正跟的近似值,使之逐步精确,最后得到精度要求的结果。
步骤:
1.构造迭代公式f(x),迭代公式必须是收敛的。
2.计算x1,x1=f(x0).
3.判断|x1-x0|是否满足精度要求,如不满足则重复上述步骤。
4.输出x1,即为方程的近似解。
Newton迭代法
思想:
设r是
的根,选取
作为r的初始近似值,过点
做曲线
的切线L,L的方程为
,求出L与x轴交点的横坐标
,称x1为r的一次近似值。
过点
做曲线
的切线,并求该切线与x轴交点的横坐标
,称
为r的二次近似值。
重复以上过程,得r的近似值序列,其中,
称为r的
次近似值
步骤:
1.计算原函数的导数f’(x);构造牛顿迭代公式
2.计算
若f’(x0)=0,退出计算,否则继续向下迭代。
3.若|x1-x0|满足精度要求,x1即为方程的近似解。
弦截法
思想:
为加速收敛,改用两个端点都在变动的弦,用差商替代牛顿迭代公式的导数f’(x)。
步骤:
1.构造双点弦法的公式
2.计算x2=x1-f(x1)(x1-x0)/f(x1)-f(x0);
3.判断f(x2)是否满足精度要求,若没有则按照上述步骤继续迭代,否则输出即为方程的近似解。
第3章测试结果及分析
测试结果
函数图像
函数Y=x5-3x3+x-1
二分法(表1-1,1-2,1-3)
[,]
k
xk
k
xk
k
xk
0
5
10
1
6
11
2
7
12
3
8
13
4
9
14
表1-1
区间[,]
k
xk
k
xk
k
xk
0
5
10
1
6
11
2
7
12
3
8
13
4
9
14
-1
表1-2
区间[,]
k
xk
k
xk
k
xk
0
7
14
1
8
15
2
9
16
3
10
17
4
11
18
5
12
6
13
表1-3
简单迭代法(表)
初值
k
xk
k
xk
k
xk
1
7
13
2
8
14
3
9
15
4
10
16
5
11
17
6
12
18
表2-1
初值-1
k
x
1
-1
2
-1
表2-2
初值结果x=
k
xk
k
xk
k
xk
1
8
15
2
9
16
3
10
17
4
11
18
5
12
19
6
13
20
7
14
表2-3
牛顿迭代法(表,3-3)
初值结果x=
k
xk
k
xk
1
4
2
5
3
6
表3-1
初值-1结果x=
k
x
1
-1
2
-1
表3-2
初值结果x=
k
xk
k
xk
1
5
2
6
3
7
4
8
表3-3
双点弦法(表,4-3)
区间[,]结果x=
k
xk
f(xk)
k
xk
f(xk)
1
5
2
6
3
7
4
8
表4-1
区间[,]结果x=-1
k
xk
f(xk)
1
2
3
4
-1
表4-2
区间[,]结果x=
k
xk
f(xk)
1
2
3
4
5
表4-3
从测试结果可以看出二分法和简单迭代法的收敛速度远大于牛顿迭代和弦截法的收敛速度。
二分法和简单迭代法的公式易于构造和计算,牛顿迭代法虽然收敛高,但要求导数,计算的复杂度高!
双点弦法随稍慢于牛顿跌代法,可以用差商代替牛顿迭代法中的导数,降低了计算的复杂度!
附录:
源程序清单
#include
#include<>
usingnamespacestd;
doublefoot=;//定义寻根步长
inta=-8,b=8;
double*rn=newdouble[5];//解的区间
double*r=newdouble[5];//方程近似解
intm=0;//根的个数
intx_count;
doubleprecision=;//精度要求
//函数的表达式(x^5-3x^3+x-1)
doublef(doublex){
return(pow(x,5)-3*pow(x,3)+x-1);
}
voidinit(){//根据函数图像确定根的区间和迭代初值
r[0]=;
r[1]=-1;
r[2]=;
rn[0]=;
rn[1]=;
rn[2]=;
}
//寻找根的区间
voidsearch(){//若没有给出区间和初值,进行逐步搜索有根区间
for(inti=0;i*foot-8<8;i++){
if(f(i*foot-8)*f((i+1)*foot-8)<0){
rn[m]=i*foot-8;
m++;
}
}
}
//=====================二分法==========================
doubleDichotomy(doublea,doubleb){
doublemid=0;
inti=0;
while(fabs(b-a)>precision){
mid=(a+b)/2;
if(f(a)*f(mid)<=0)b=mid;//判断与端点函数值得符号
elsea=mid;
cout<}
r[x_count++]=mid;
returnmid;//返回最终结果
}
//================简单迭代法=========================
//构造迭代公式
doublefitera(doublex){
doubleresult=0;
doublexx=3*pow(x,3)-x+1;
if(xx<=0){
xx=-xx;
returnpow(xx,*(-1);}
else
returnpow(xx,;
}
//简单迭代
doubleitera(doublex0){
cout<doublex1=fitera(x0);
while(fabs(x1-x0)>precision){
x0=x1;
x1=fitera(x0);//没有到达精度要求继续迭代
cout<}
returnx1;//返回最终结果
}
//===============牛顿迭代法==================
//计算函数的一阶导数fderivatives(doublex)
doublefderivatives(doublex){
return5*pow(x,4)-9*(x,2)+1;
}
//构造牛顿迭代公式newtonitera(doublex)
doublenewtonitera(doublex){
if(fderivatives(x)==0)return-1;//若导数为0则停止迭代
else
returnx-(f(x)/fderivatives(x));
}
//牛顿迭代
doublenewton(doublex0){
doublex1=newtonitera(x0);
while(fabs(x1-x0)>precision){
x0=x1;
if(newtonitera(x0)==-1)break;
x1=newtonitera(x0);//继续迭代
cout<}
returnx1;//返回最终结果
}
//==================双点弦法迭代======================
//构造弦截法的迭代公式
doubletwopointchord_f(doublex0,doublex1){
returnx1-(f(x1)/(f(x1)-f(x0)))*(x1-x0);
}
//双点弦法迭代
doubletwopointchord(doublex0,doublex1){
doublex3=twopointchord_f(x0,x1);
cout<while(fabs(f(x3))>precision){
cout<<"f(x3)"<x0=x1;
x1=x3;
x3=twopointchord_f(x0,x1);//没有到达精度要求继续迭代
//cout<}
cout<returnx3;//返回最终结果
}
//测试
voidmain(){
init();//初始化区间和迭代初值
/*测试代码输出每次的迭代结果和最终结果
cout<<"------------------------二分法----------------------"<for(inti=0;i<3;i++){
doubleresult=0;
cout<<"有根区间为["<result=Dichotomy(rn[i],rn[i]+foot);//将区间端点带入公式
cout<<"求得近似解为"<}
cout<<"------------------------迭代法----------------------"<for(i=0;i<3;i++){
doubleresult=0;
cout<<"有根区间为["<doublex0=r[i];//取得初值
result=itera(x0);//带入公式
cout<<"求得近似解为"<}
cout<<"------------------------牛顿迭代----------------------"<for(i=0;i<3;i++){
doubleresult=0;
cout<<"有根区间为["<doublex0=r[i];//取得初值
result=newton(x0);//带入公式
cout<<"求得近似解为"<}
cout<<"------------------------弦截法----------------------"<for(i=0;i<3;i++){
doubleresult=0;
cout<<"有根区间为["<result=twopointchord(rn[i],rn[i]+foot);//将区间端点带入公式
cout<<"求得近似解为"<}
/*
学生实验心得
在这次实验中,通过编程将二分法、简单迭代法、Newton迭代法、弦截法(割线法、双点弦法)以代码的方式实现,这不仅是一次实践过程,更是对这些求解方程的方法的深入理解,体会们各自的算法思想。
也提高的我对数值计算中的经典方法其中蕴藏的算法思想的兴趣,这些思想方法对以后的问题的解决以及编程思想都是很有帮助的。
虽然在实验过程中遇到了一些问题,但是通过查询资料以及不断的调试程序都得以解决。
这也让我认识到只要深入理解,坚持不懈,就一定能够成功的。
我会将这次的实验的宝贵经验实践到以后的学习中,希望能在不断的锻炼中提升自己!
学生(签名):
年月日
指导
教师
评语
成绩评定:
指导教师(签名):
年月日