计算方法与误差 实验报告.docx
《计算方法与误差 实验报告.docx》由会员分享,可在线阅读,更多相关《计算方法与误差 实验报告.docx(21页珍藏版)》请在冰豆网上搜索。
计算方法与误差实验报告
方程求根—牛顿迭代法
摘要
通过对牛顿迭代法的编程练习,掌握方程求根的牛顿迭代法的算法,进一步体会牛顿迭代法的特点。
关键字:
牛顿迭代;方程求根;编程;运算次数
1、算法
流程图:
算法:
用迭代法的结构,增设4个工作单元F0,F0’,F1,F1’,并把用作终止迭代的误差控制改为两个|x1-x0|1.1、准备:
选定初始值x0,计算F0=f(x0);F0’=f’(x0),如果F0’=0,则输出“方法失败”并结束。
1.2、迭代:
对k=1,2,…,N,做:
1)x1=x0-F0/F0’,
2)计算F1=f(x1);F1’=f’(x1)
3)若F1’=0,则输出“方法失败”并结束。
1.3、控制:
若|x1-x0|1.4、k>N时输出“经N次迭代无满足要求的近似解”结束。
2、实验步骤
1)完成牛顿迭代法的程序设计及录入;
2)完成程序的编译和链接,并进行修改;
3)用书上的例子对程序进行验证,并进行修改;
4)分别输入两组不同的根的误差限,观察运算次数的变化;
5)分别取不同的初时值x0,观察运算结果的变化;
6)完成实验报告。
3、实验结果
3.1、经编译、链接及例子验证结果正确的源程序:
#include
#include
#defineN100
#defineeps5e-6
#definedelta1e-6
voidmain()
{
floatx0,x1,d,f1;
intk=0;
printf("请输入迭代初值x0:
");
scanf("%f",&x0);
printf("x(0)=%f\n",x0);
do
{
x1=x0-(x0*x0*x0+x0*x0-3*x0-3)/(3.0*x0*x0+2*x0-3);
if(k++>N||fabs(3.0*x1*x1+2*x1-3){
printf("\n发散");
break;
}
d=fabs(x1)<1?
x1-x0:
(x1-x0)/x1;
x0=x1;
printf("x(%d)=%f\t",k,x0);
}
while(fabs(d)>eps&&fabs(x1*x1*x1+x1*x1-3*x1-3)>delta);
printf("方程的根为:
%f\n",x1);
}
3.2、实例验证结果:
1)方程:
f(x)=x3+x2-3x-3=0
2)输入初始参数:
x0=1,EPS=1e-6
3)结果输出:
请输入迭代初值x0:
1.0
x(0)=1.000000
x
(1)=3.000000
x
(2)=2.200000
x(3)=1.830151
x(4)=1.737795
x(5)=1.732072
x(6)=1.732051
方程的根为:
1.732051
Pressanykeytocontinue
3.3、改变初值x0的值为:
x0=1.5,EPS不变,仍为1e-6,其结果为:
请输入迭代初值x0:
1.0
x(0)=1.000000
x
(1)=3.000000
x
(2)=2.200000
x(3)=1.830151
x(4)=1.737795
x(5)=1.732072
x(6)=1.732051
方程的根为:
1.732051
Pressanykeytocontinue
3.4、改变初值x0的值为:
x0=0.1,EPS不变,仍为1e-6,其结果为:
请输入迭代初值x0:
0.1
x(0)=0.100000
x
(1)=-1.087365
x
(2)=-0.989802
x(3)=-0.999899
x(4)=-1.000000
方程的根为:
-1.000000
Pressanykeytocontinue
3.5、改变EPS的值为:
EPS=5e-4,x0不变,仍为1,其结果为:
请输入迭代初值x0:
1.0
x(0)=1.000000
x
(1)=3.000000
x
(2)=2.200000
x(3)=1.830151
x(4)=1.737795
x(5)=1.732072
x(6)=1.732051
方程的根为:
1.732051
Pressanykeytocontinue
3.6.改变EPS的值为:
EPS=1e-3,x0不变,仍为1,其结果为:
请输入迭代初值x0:
1.0
x(0)=1.000000
x
(1)=3.000000
x
(2)=2.200000
x(3)=1.830151
x(4)=1.737795
x(5)=1.732072
方程的根为:
1.732072
Pressanykeytocontinue
4、分析和讨论
1.输入不同的初值x0,迭代次数的变化情况
答:
初值X0越大,迭代的次数越多
2.输入不同的误差限EPS,迭代次数的变化情况
答:
随着误差限EPS的增大,迭代次数会相应的减少。
5、心得
①调试过程中遇到的问题和解决对策;②经验体会等。
答:
通过实验进一步了解牛顿迭代法的计算特点,从而使我对牛顿迭代的知识了解更深。
方程求根——二分法
摘要
通过对二分法的编程练习,掌握方程求根的二分法的算法,进一步体会二分法的特点。
关键词:
求根;二分法;编程;估算次数
1、算法
流程图:
1)准备:
计算f(x)在有根区间[a,b]端点处的值f(a),f(b)。
2)二分:
计算f(x)在区间中点c=
处的函数值f(c)。
3)判断
•若f(c)与f(a)异号,则根位于区间[a,c]内,以c代替b;
•若f(c)与f(a)同号,则根位于区间[c,b]内,以c代替a;
反复执行步2和步3,直到区间[a,b]长度缩小到允许误差范围之内或f(c)=0,此时区间中点c即可作为所求的根。
2、实验步骤
1)完成二分法的程序设计及录入;
2)完成程序的编译和链接,并进行修改;
3)用书上的例子对程序进行验证,并进行修改;
4)对比估算次数与实际二分次数;
5)输入不同的区间初值a,b,查看二分次数的变化;
6)输入不同的误差限,查看二分次数的变化;
7)完成实验报告。
3、实验结果
3.1经编译、链接及例子验证结果正确的源程序:
#include
#include
#defineeps5e-6
#definedelta1e-6
voidmain()
{
floata=1,b=2,fa,fb,fab,c,fc;
intn=1;
fa=a*a*a+a*a-3*a-3;
fb=b*b*b+b*b-3*b-3;
fab=fa*fb;
while
(1)
{
if(fab>0)
{
printf("不能使用二分法");
break;
}
c=(a+b)/2;
fc=c*c*c+c*c-3*c-3;
if(fabs(fc)elseif(fa*fc<0){b=c;fb=fc;}
else{a=c;fa=fc;}
if(b-aprintf("%d\t%f\t%f\n",n++,c,fc);
}
printf("\n方程的根是:
%f",c);
}
3.2、实例验证结果:
1)方程:
f(x)=x3+x2-3x-3=0
2)输入初始参数:
a=1,b=2,EPS=5e-6
3)结果输出:
1.改变a,b的值为:
a=0,b=2,EPS不变,仍为5e-6,其结果为:
4.改变EPS的值为:
EPS=5e-4,a,b不变,仍为a=1,b=2,其结果为:
4、分析和讨论
1.估算次数与实际二分次数的分析和讨论
答:
估算的次数与实际二分次数相等,即估算好多次,就二分了好多次
2.输入不同的区间初值a,b,二分次数的变化情况
答:
输入的区间范围越大,要达到相同的精确值,二分次数会相应的增加
3.输入不同的误差限EPS,二分次数的变化情况
答:
随着误差限EPS的增大,二分次数会相应的减少。
5、心得
①调试过程中遇到的问题和解决对策;②经验体会等。
答:
通过二分计算在电脑中的演示更一步了解了二分法的特点:
用对分区间的方法根据分点处函数f(x)值的符号逐步将有根区间缩小,使在足够小的区间内,方程有且仅有一个根.二分法收敛速度较慢,在编程过程中,对变量的定义采用哪种类型,主要是对条件的判断做准确分析,对中断条件的准确把握,在调试过程中,对k值采用哪种类型的定义。
对k值的输出有很大关系,
曲线拟合—最小二乘法
摘要
了解最小二乘法的基本原理,熟悉最小二乘算法;掌握最小二乘进行曲线拟合的编程,通过程序解决实际问题。
关键词:
曲线拟合;最小二乘法;拟合次数
1、算法
1)输入数据节点数n,拟合的多项式次数m,循环输入各节点的数据xj,yj(j=0,1,…,n-1)
2)由xj求S;由xj,yj求T:
Sk=
(k=0,1,2,…2*m)
Tk=
(k=0,1,2,…m)
3)由S形成系数矩阵数组ci,j:
c[i][j]=S[i+j](i=0,1,2,…m,j=0,1,2,…,m);由T形成系数矩阵增广部分ci,m+1:
c[i][m+1]=T[i](i=0,1,2,…m)
4)对线性方程组CA=T[或
],用列主元高斯消去法求解系数矩阵A=(a0,a1,…,am)T
2、实验步骤
1)完成最小二乘法进行曲线拟合的程序设计及录入、编辑;
2)完成程序的编译和链接,并进行修改;
3)用书上P105例2的例子对程序进行验证,并进行修改;
4)用完成的程序求解下面的实际问题。
5)完成实验报告。
3、实验结果
3.1、经编译、链接及例子验证结果正确的源程序:
#include
#defineN10
#defineM20
#defineDELTA1e-7
#include
voidmain()
{
intn,m,i,j,S;
intk=0;
floatx[N],y[N],s[2*M]={0},t[M]={0},c[M+1][M+2],z[M],A,q,sum=0;
doublel;
printf("输入数据节点数n:
");
scanf("%d",&n);//输入n
printf("拟合的多项式次数m:
");
scanf("%d",&m);//输入m
printf("x[i]:
");
for(i=0;i{
scanf("%f",&x[i]);//输入x[i]
}
printf("y[i]:
");
for(i=0;i{
scanf("%f",&y[i]);//输入y[i]
}
printf("\n");
/*-------------------
求s,t
-----------------------*/
for(i=0;i<=2*m;i++)
{
for(j=0;j{
s[i]=s[i]+pow(x[j],i);
}
}
for(i=0;i<=m;i++)
{
for(j=0;j{
t[i]=t[i]+y[j]*pow(x[j],i);
}
}
for(i=0;i<=m;i++)
{
for(j=0;j<=m;j++)
{
c[i][j]=s[i+j];
}
c[i][m+1]=t[i];
}
/*输出c[i][j]*/
for(i=0;i<=m;i++)
for(j=0;j<=m+1;j++)
{
printf("%-10.0f",c[i][j]);
if(j==m+1)
printf("\n");
}
/*用高斯列主元解方程*/
for(j=k,S=k;j{
A=fabs(c[k][k]);
for(i=k;i{
if(A{
A=fabs(c[i][j]);S=i;//找出每列最大数
}
}
if(A{printf("A奇异,结束程序.");break;}
if(S!
=k)
{
for(j=k;j<=m+1;j++)
{
q=c[k][j];c[k][j]=c[S][j];c[S][j]=q;//将最大数所在行与第K行的数交换
}
}
for(i=k+1;i<=m;i++)
{
j=k;
l=c[i][j]/c[k][j];//计算消元因子
for(j=k;j<=m+1;j++)
c[i][j]=c[i][j]-l*c[k][j];
}
for(i=0;ifor(j=0;j<=m+1;j++)
{
printf("%-15f",c[i][j]);//输出中间过程
if(j==m+1)
printf("\n");
}
j=k;printf("\n");
}
/*回代*/
if(fabs(c[m][m])printf("A奇异,结束程序");
else
{
z[m]=c[m][m+1]/c[m][m];
printf("z[%d]=%-11f\n",m+1,z[m]);
for(i=m-1;i>=0;i--)
{
for(j=i+1,sum=0;j<=m;j++)
sum=sum+c[i][j]*z[j];
z[i]=(c[i][m+1]-sum)/c[i][i];
printf("z[%d]=%-11f\n",i+1,z[i]);
}
}
/*计算误差*/
floatp=0,d,e=0;;
for(i=0;i{
p=z[0];
for(j=1;j<=m;j++)
{
d=pow(x[i],j);
p+=d*z[j];
}
e+=(p-y[i])*(p-y[i]);
}
printf("\n误差计算为:
%f.\n",e);//输出误差
}
3.2、实例验证结果:
1)输入初始参数:
n=9,m=2
X:
1345678910
Y:
1054211234
2)结果输出:
4、实际应用
问题:
作物体运动的观测实验,得出以下实验测量数据,用最小二乘拟合求物体的运动方程。
时间t(秒)
0
0.9
1.9
3.0
3.9
5.0
距离s(cm)
0
10
30
50
80
110
解题步骤:
1)画草图
2)确定拟合方程次数为1:
用完成的程序输入数据,求取拟合方程中的未知数,得出方程:
f(x)=-7.855058+22.253763*x
计算误差:
答:
误差为209.858978
3)确定拟合方程次数为2:
用完成的程序输入数据,求取拟合方程中的未知数,得出方程:
f(x)=-0.583343++11.081374*x+2.248814*(x^2)
计算误差:
答:
误差为23.292877
5、分析和讨论
1.结合实际问题,进行拟合次数的分析和讨论:
答:
通过实验M值取1—9的时候。
m=8的误差最小为0.000015。
m继续增加会使得误差增大。
所以做最小二乘法时应取适当的m值,可以多次实验,去验证最合适的拟合次数。
6、心得
①调试过程中遇到的问题和解决对策;②经验体会等。
答:
编程过程中用到的for循环很多,很容易忘记打大括号,而且在循环输入数组时,加上大括号才对,这个问题没有想通,就数组输入的地方那调试了很久才弄出来。