数值分析实验报告.docx
- 文档编号:9865557
- 上传时间:2023-02-07
- 格式:DOCX
- 页数:55
- 大小:847.83KB
数值分析实验报告.docx
《数值分析实验报告.docx》由会员分享,可在线阅读,更多相关《数值分析实验报告.docx(55页珍藏版)》请在冰豆网上搜索。
数值分析实验报告
学生学号
实验课成绩
武汉理工大学
学生实验报告书
实验课程名称:
数值分析
开课名称:
计算机科学与技术学院
指导老师姓名:
熊盛武
学生姓名:
学生专业班级:
20011——2012学年第二学期
第一次试验
(1)二分法计算流程图:
b-a>e
b=x
a=x
f(a)f(x)<0
i++
x=(a+b)/2
t=(a+b)/2
输出近似根t,循环次数i
结束
方程x*x*x-x-1=0
开始
b-a>e
求根区间[a,b]循环次数i,i=0
否
是
是
否
是
否
(2)简单迭代法算法流程图:
(3)牛顿迭代法流程图:
(4)弦截法算法程序流程图:
二分法程序源代码:
#include
#include
#definef(x)(x*x*x-x-1)
usingnamespacestd;
intmain()
{
inti;
floatx,t,a,b,e;
cout<<"请输入求根区间a,b"<<"控制变量e"< cin>>a>>b>>e;i=0; while((b-a)>e) { i++; x=(a+b)/2; if(f(a)*f(x)<0)b=x; if(f(a)*f(x)>0)a=x; } t=(a+b)/2; cout<<"在求根区间a,b间近似根t="< cout<<"所需二分法次数i="< return0; } 调试过程,实验结果及分析: 计算x*x*x-x-1=0在[1,2]内的近似根。 精度达到0.0001时,程序运行结果如下图: 当精度达到0.00001时,程序运行如下图: 调试过程中如果把while((b-a)>e)改为while((b-a) 从而跳过循环体直接输出前面输入的数据。 由运行结果看出: 精度达到0.0001时,二分法次数为14。 精度达到0.00001时,二分法次数为17。 精度要求越高,二分法次数越多。 二分法缺点: 逼近速度较慢。 二分法对有根区间逐步逼近得到更精确的近似根,二分法不采用等步长扫描,而是在有根区间[a,b]中,取中点,然后计算中点值,判断中点对应函数值和端点函数值乘积的正负来确定新的端点,当有根区间长度小于精确度时得到近似根。 如果没有区间长度和精度大小的判断,程序是一个死程序,得不到近似根。 简单迭代法程序源代码: #include #include doubles(doublet) { return(t+1); } usingnamespacestd; intmain() { inti; doublex,x0,x1,e; cout<<"请输入迭代初始值x0"<<",和控制精度e"< cin>>x0>>e; i=0; while(fabs(x1-x0)>e) { i++; x1=pow(s(x0),1.0/3.0); x0=x1; x1=pow(s(x0),1.0/3.0); } x=(x1+x0)/2; cout<<"近似根x="< cout<<"所需迭代次数i="< return0; } 调试过程,实验结果及分析: 计算x*x*x-x-1=0在[1,2]内的近似根。 精度达到0.0001时,程序运行结果如下图: 当精度达到0.00001时,程序运行如下图: 当循环体程序代码如下: x1=pow(s(x0),1/3); x0=x1; x1=pow(s(x0),1/3); 时会出现程序运行结果的界面,但是输出的近似根是1,迭代次数是1,这是因为x1=pow(s(x0),1/3)与三次求根函数式的数据类型不符。 导致x1=pow(s(x0),1/3)不再是三次求根的函数式 由运行结果看出: 精度达到0.0001时,简单迭代法迭代次数为5. 精度达到0.00001时,简单迭代法迭代次数为6。 精度要求越高,简单迭代法迭代次数越多。 简单迭代法归结于找直线和曲线的交点的横坐标,其中迭代法的效果并不是总能令人满意的。 例如: 该程序中简单迭代法另一种等价形式 x=x*x*x-1对此建立迭代公式: x(k+1)=x(k)*x(k)*x(k)-1 迭代初始值x0=1.5,则有x1=2.375,x2=12.39.继续迭代下去已经没有必要了,为 结果显然会越来越大,不可能区域某个极限。 这种不收敛的迭代过程是发散的,一个发散的迭代过程,显然其结果是毫无价值的。 二分法和简单迭代法比较: 当精度都是0.0001,所求结果为: 1.32474时,简单迭代法迭代次数比二分法少9次,当精度都是0.00001,所求结果都为: 1.32472时,简单迭代法迭代次数比二分法少11次。 简单迭代法逼近速度比二分法好,计算的效率比二分法提高了很多精度要求越高,简单迭代法的优势也越明显。 二分法不能用于求偶数重根和复根,多用于为其他求根方法提供初始近似值。 简单迭代法的迭代过程可能是收敛的也可能是发散的,简单迭代法对迭代公式有要求,迭代公式必须是收敛的,即结果逐渐趋近于某个极限。 Aitken算法程序源代码: #include #include doubles(doublet) { return(t*t*t-1); } usingnamespacestd; intmain() { inti; doublex,x0,x1,x2,e; cout<<"请输入迭代初始值x0"<<",和控制精度e"< cin>>x0>>e; i=0; while(fabs(x0*x0*x0-x0-1)>e) { i++; x1=s(x0); x2=s(x1); x0=x2-(x2-x1)*(x2-x1)/(x2-2*x1+pow((x1+1),1.0/3.0)); } x=x0; cout<<"近似根x="< cout<<"所需迭代次数i="< return0; } 调试过程,实验结果及分析: 计算x*x*x-x-1=0在[1,2]内的近似根。 精度达到0.0001时,程序运行结果如下图: 当将x=x0;改成x=x1,输出结果近似根为1.32517,迭代次数为5,这与要求得到的试验结果1.32472有一些差距,这是有循环语句i++; x1=s(x0); x2=s(x1); x0=x2-(x2-x1)*(x2-x1)/(x2-2*x1+pow((x1+1),1.0/3.0));执行顺序决定的近似根式子应该是x=x0; 由运行结果看出: 精度达到0.0001时,Aitken迭代法迭代次数为5. Aitken迭代法是将迭代值在迭代一次,此时对于发散的x(k+1)=x(k)*x(k)*x(k)-1迭代公式,经过Aitken迭代法处理后却获得了相当好的收敛性。 Aitken迭代法和二分法的比较: 当精度都是0.0001时,Aitken迭代法迭代次数为5.,比二分法少9次,而且Aitken迭代法所求出的近似根为: 1,32472,更接近理想值,Aitken迭代法是将迭代值在迭代一次从迭代次数和所求根的差异上可以看出Aitken迭代法是一种加速迭代法。 牛顿迭代法程序源代码: #include #include doubles(doublet) { returnt-(t*t*t-t-1)/(3*t*t-1); } usingnamespacestd; intmain() { inti; doublex,x0,x1,x2,e; cout<<"请输入迭代初始值x0"<<",和控制精度e"< cin>>x0>>e; i=0; x1=x0; while(fabs(s(x1)-x1)>e) { i++; x2=s(x1); x1=x2; } x=(x1+x2)/2; cout<<"近似根x="< cout<<"所需迭代次数i="< return0; } 调试过程,实验结果及分析: 计算x*x*x-x-1=0在[1,2]内的近似根。 精度达到0.00001时,程序运行结果如下图: 由运行结果看出: 精度达到0。 00001时,牛顿迭代法迭代次数为3 x2=s(x1);x1=x2;这两句顺序不能换过来,当换过来时,错误如下 c: \programfiles\microsoftvisualstudio\myprojects\erww\q.cpp(26): fatalerrorC1004: unexpectedendoffilefound 执行cl.exe时出错.: 这是因为在执行循环体之前没有对x2赋值,系统无法识别赋值到x1的值是多少,因此也无法的到想要的结果。 从运行结果看出: 牛顿迭代法有很好的收敛性。 在精度要求相同时,牛顿迭代法迭代次数比二分法,简单迭代法,Aitken迭代法都要少,牛顿迭代法是一种更快的迭代法。 牛顿迭代法是将非线性方程逐步转化为某些线性方程来求解,这是牛顿迭代法的基本思想。 将牛顿迭代法应用于以下方程求根: 1x=(2-e^x+x*x)/3 23*x*x-e^x=0 对于x=(2-e^x+x*x)/3应用牛顿迭代法程序运行结果如下图: 对于3*x*x-e^x=0应用牛顿迭代法程序运行结果如下图: 弦截法程序源代码: #include #include doubles(doublet) { returnt*t*t-t-1; } usingnamespacestd; intmain() { inti; doublex,x0,x1,x2,e; cout<<"请输入迭代初始值x0,x1"<<",和控制精度e"< cin>>x0>>x1>>e; i=0; while(fabs(x1-x0)>e) { i++; x2=x1-s(x1)*(x1-x0)/(s(x1)-s(x0)); x0=x1; x1=x2; } x=(x1+x2)/2; cout<<"近似根x="< cout<<"所需迭代次数i="< return0; } 调试过程,实验结果及分析: 对于x0=1,x1=2利用弦截法程序运行结果如下图: 弦截法对精度0.00001,需要迭代7次才能得到近似根,收敛速度比牛顿法慢些,但它的计算量比牛顿迭代法少,特别是导数的计算比较复杂时,弦截法更现实了它的优越性。 对于x=(2-e^x+x*x)/3应用弦截运行结果如下图: 对于3*x*x-e^x=0应用牛顿迭代法程序运行结果如下图: 弦截法局部收敛的速度比牛顿法略慢一些,弦截法计算过程中没有导数的计算,弦截法的计算量比牛顿法少。 实验小结及体会: 试验中练习了方程求根的迭代法,在选择和使用各种迭代格式中,最重要的是判断其收敛性及了解其收敛速度。 在实际计算中,不一定都要判断迭代格式的收敛性才予使用,也可以根据对问题解的了解及获得的迭代序列来判断是否收敛于所要的根,但要注意,对于局部收敛的迭代格式(如牛顿迭代法)迭代初值的选取非常重要。 尽管每种数值方法有它本身的局限性,但它们还是很有效的。 因此应该了解每一种方法的来龙去脉,尤其是它的困难所在,并通过计算机实习来熟悉和掌权这些方法.。 第二次试验 (1)Lagrange插值公式算法流程图 (2)Newton插值公式算法流程图 (三)分段插值公式算法流程图 (四)Hermite公式流程图 编程计算f(x)的近似值 (一)Lagrange插值: 拉格朗日插值程序源代码 #include #include usingnamespacestd; intmain() { inti,j,n; doublea[100],b[100]; cout<<"请输入插值节点控制数: n"< cin>>n; cout<<"请输入n+1个插值点: "< for(i=0;i<=n;i++) { cin>>a[i]>>b[i]; } doublef,x,tmp; cout<<"请输入所求函数值对应的x点"< cin>>x; f=0; for(i=0;i<=n;i++) { tmp=1; for(j=0;j<=n;j++) if(i==j)continue; elsetmp=tmp*(x-a[j])/(a[i]-a[j]); f=f+tmp*b[i]; } cout<<"所求函数值为f_x="< return0; (二)Newton插值: 牛顿插值法程序源代码 #include #include usingnamespacestd; intmain() { inti,j,n; doublea[100],b[100]; cout<<"请输入插值节点控制数: n"< cin>>n; cout<<"请输入n+1个插值点: "< for(i=0;i<=n;i++) { cin>>a[i]>>b[i]; } doublef,x,tmp; cout<<"请输入所求函数值对应的x点"< cin>>x; for(i=0;i for(j=n;j>i;j--) { b[j]=(b[j]-b[j-1])/(a[j]-a[j-1-i]); } tmp=1; f=b[0]; { for(i=0;i { tmp=tmp*(x-a[i]); f=f+tmp*b[i+1]; } cout<<"所求函数值为f_x="< } return0; } (三)调试过程,实验结果及分析: (1)利用拉格朗日插值对于f(x)=e^x,x0=0,x1=0.5利用线性插值计算f(0.25)的近似值 运行结果如下图: 对于x0=0.5,x1=1.0利用线性插值计算f(0.75)的近似值 运行结果如下图: 对于x0=0,x1=0.5,x2=2.0利用二次插值计算f(0.25)的近似值 运行结果如下图: 对于x0=0,x1=0.5,x2=2.0利用二次插值计算f(0.75)的近似值 运行结果如下图: (2)利用牛顿插值对于f(x)=e^x,x0=0,x1=0.5利用线性插值计算f(0.25)的近似值 运行结果如下图: 对于x0=0.5,x1=1利用线性插值计算f(0.75)的近似值 运行结果如下图: 对于x0=0,x1=0.5,x2=2.0利用二次插值计算f(0.25)的近似值 运行结果如下图: 对于x0=0,x1=0.5,x2=2.0利用二次插值计算f(0.75)的近似值 运行结果如下图: (3)运行结果的比较: 拉格朗日插值和牛顿插值计算出的结果相同,但是牛顿插值法的计算量较少。 拉格朗日法形式对称,结构简单,便于在计算机上实现,只是计算量大。 二次插值因为在取点更准确和计算复杂,所得到的结果精确度更好。 编程计算f(x)= 的近似值 (一)分段插值: 分段线性插值法程序源代码 #include #include usingnamespacestd; intmain() { inti,j,n; doublea[10],b[10],x,f,tmp; cout<<"请输入插值节点的个数: n"< cin>>n; cout<<"请输入n个插值节点: "< for(i=0;i { cin>>a[i]>>b[i]; } cout<<"请输入所求函数值对应的x点"< cin>>x; f=0; if(x else for(i=1;i { if(x } loop: for(i=0;i<=1;i++) { tmp=1; for(j=0;j<=1;j++) if(i==j)continue; elsetmp=tmp*(x-a[j])/(a[i]-a[j]); f=f+tmp*b[i]; } cout<<"所求函数值为"< return0; } 分段抛物线插值法程序源代码 #include #include usingnamespacestd; intmain() { inti,j,n; doublea[10],b[10],x,f,tmp; cout<<"请输入插值节点的个数: n"< cin>>n; cout<<"请输入n个插值节点: "< for(i=0;i { cin>>a[i]>>b[i]; } cout<<"请输入所求函数值对应的x点"< cin>>x; f=0; if(x else
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数值 分析 实验 报告