数值分析实验报告.docx

上传人:b****8 文档编号:9865557 上传时间:2023-02-07 格式:DOCX 页数:55 大小:847.83KB
下载 相关 举报
数值分析实验报告.docx_第1页
第1页 / 共55页
数值分析实验报告.docx_第2页
第2页 / 共55页
数值分析实验报告.docx_第3页
第3页 / 共55页
数值分析实验报告.docx_第4页
第4页 / 共55页
数值分析实验报告.docx_第5页
第5页 / 共55页
点击查看更多>>
下载资源
资源描述

数值分析实验报告.docx

《数值分析实验报告.docx》由会员分享,可在线阅读,更多相关《数值分析实验报告.docx(55页珍藏版)》请在冰豆网上搜索。

数值分析实验报告.docx

数值分析实验报告

 

学生学号

实验课成绩

 

武汉理工大学

学生实验报告书

 

实验课程名称:

数值分析

开课名称:

计算机科学与技术学院

指导老师姓名:

熊盛武

学生姓名:

学生专业班级:

 

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

for(i=1;i

{

if(x

}

loop:

for(i=0;i<=2;i++)

{

tmp=1;

for(j=0;j<=2;j++)

if(i==j)continue;

elsetmp=tmp*(x-a[j])/(a[i]-a[j]);

f=f+tmp*b[i];

}

cout<<"所求函数值为"<

return0;

}

调试过程,实验结果及分析:

1、分段线性插值程序运行结果如下:

2、分段抛物线插值程序运行结果如下:

3、由运行结果可以看出:

分段抛物线插值比分段线性插值更准确,这是因为抛物线插值在所求点的附近选取的点,并且线性插值和抛物线插值在所考虑区间内插值得到的数值精确度比在考虑区间外所得到的数值的精确度要高,这说明了内插比外推插值效果要好。

 

第二次实验小结及体会

1、插值法是数值分析中的一类重要方法,有着广泛的应用。

本次试验中几种数值方法及有关概念和理论是数值分析最基本的内容

2、拉格朗日插值多项式是研究数值微积分与微分方程数值解的重要工具,但该方法计算量很大,且误差估计很困难,理论上还是比较重要。

3、牛顿插值多项式是拉格朗日插值多项式的变形,具有继承性,比拉格朗日插值多项式节省计算量,试验中用到了均差的概念,当节点数增加或减少时,只需将原有的计算结果增加或减少一项,着也是牛顿插值比拉格朗日插值方便的地方,应当注意。

4、分段低次多项式插值由于具有良好的稳定性与收敛性,且算法简单,可根据节点处函数值的具体情况,采用不同的插值公式,解决了曲线平滑性的问题,更便于应用。

 

第三次试验

 

(一)复化梯形求算法积流程图

 

(三)变步长梯形求积算法流程图

(二)复化Simpson求积算法流程图

(四)Romberg公式求积流程图

编程计算积分

(一)复化梯形:

复化梯形求积程序

#include

#include

doublef(doublet)

{

return1/(1+t*t);

}

usingnamespacestd;

intmain()

{

inti,n;

doubleh,a,b,T,temp,Tn;

cout<<"请输入求积区间:

"<

cin>>a>>b;

cout<<"请输入区间等分数:

"<

cin>>n;

h=(b-a)/n;

temp=0;

T=0;

for(i=1;i

{

temp=f(a+i*h);

T=T+2*temp;

}

Tn=(f(a)+f(b)+T)*h/2;

cout<<"经过复化梯形求积所得积分值T"<

"<

return0;

}

调试过程,实验结果及分析:

1/(x*x)在区间[0,1]上8等分后,程序运行结果如下:

对区间等分后求每个子区间上的积分值,然后将每个子区间的积分值相加,就得到整个积分区间上的积分值,梯形公式具有一次代数精度。

(二)复化Simpson:

复化Simpson算法程序源代码

#include

#include

doublef(doublet)

{

return1/(1+t*t);

}

usingnamespacestd;

intmain()

{

inti,n;

doubleh,a,b,S1,S2,temp1,temp2,Sn;

cout<<"请输入求积区间:

"<

cin>>a>>b;

cout<<"请输入区间等分数:

"<

cin>>n;

h=(b-a)/n;

temp1=0;

temp2=0;

S1=0;

S2=0;

for(i=0;i

{

temp1=f(a+i*h);

temp2=f(a+(i+0.5)*h);

S1=S1+2*temp1;

S2=S2+4*temp2;

}

Sn=(f(b)-f(a)+S1+S2)*h/6;

cout<<"经过复化Simpson求积所得积分值S"<

"<

return0;

}

调试过程,实验结果及分析:

1/(x*x)在区间[0,1]上8等分后,程序运行结果如下:

复化Simpson求积公式具有三次代数精度,因此在区间和区间等分数相同时,所取得的积分值结果比梯形公式更加精确。

和梯形公式一样都是利用线性组合来计算积分的近似值。

(三)变步长梯形求积:

变步长梯形求积程序源代码

#include

#include

doubl

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 生产经营管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1