数值分析插值上机报告含代码Word格式文档下载.docx

上传人:b****8 文档编号:22428097 上传时间:2023-02-04 格式:DOCX 页数:8 大小:19.28KB
下载 相关 举报
数值分析插值上机报告含代码Word格式文档下载.docx_第1页
第1页 / 共8页
数值分析插值上机报告含代码Word格式文档下载.docx_第2页
第2页 / 共8页
数值分析插值上机报告含代码Word格式文档下载.docx_第3页
第3页 / 共8页
数值分析插值上机报告含代码Word格式文档下载.docx_第4页
第4页 / 共8页
数值分析插值上机报告含代码Word格式文档下载.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

数值分析插值上机报告含代码Word格式文档下载.docx

《数值分析插值上机报告含代码Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《数值分析插值上机报告含代码Word格式文档下载.docx(8页珍藏版)》请在冰豆网上搜索。

数值分析插值上机报告含代码Word格式文档下载.docx

多项式插值一般有两种方法,拉格朗日插值和牛顿插值。

个人认为,牛顿插值便于计算机实现,所以采用牛顿插值法来解决第一问。

但是牛顿插值公式并不十分直观,最好能将牛顿插值多项式化简。

为了化简多项式,我建立了一个多项式类,在进行多项加法和乘法时可以自动化简多项式,在逐步建立牛顿插值多项式时,该多项式会自动化为最简。

题目中还要

求在同一张图中画出原多项式和插值多项式,可以使用MFC进行画图,通过菜单选项来选择等分点的数量,然后程序会自动算出插值多项式并输出在屏幕上,接着会输出图形。

第二问:

第二问要求求出最大相对误差,本题较为特殊,其误差表达式恰好为一个多项式,所以求误差多项式后,逐点搜索该函数的绝对值的最大值。

第三问:

该问要求分析前两问所得结果,同时要求寻找更好的方法来插值。

本人使用了三次样条插值(边界条件为一阶导数相等)来求解该问题。

求三次样条函数的关键过程其实就是求解三对角方程,可以使用追赶法来求解该方程。

为了体现效果,也可以用MFC来画图,同时输出各段插值函数以及最大相对误差。

求解方法:

问题中用到的两个插值方法为牛顿插值和三次样条插值,解法与教科书中的一模一样,在此不再赘述。

程序设计:

1.牛顿插值

程序设计分为三步走:

设计多项式类在附录一的poly.h中设计牛顿插值函数在附录一的Newton_interpolation.h中设计MFC程序关键代码代码在附录一的MFC中

多项式类的声明如下:

typedefintdegree;

typedefdoublecoefficient;

//termrepresentspolynomialtermconsistingofitspowerandcoefficienttypedefstd:

:

pair<

degree,coefficient>

term;

classpolynomial{private:

//linerliststd:

list<

term>

poly;

public:

//defaultconstructorpolynomial(){};

//copyconstructorpolynomial(constpolynomial//constructapolynomialconsistingofonlyonetermcoefficient*X^degree<

/term>

<

/degree,coefficient>

从声明中可以看到,该类使用STL中的list类型来存储多项式,还实现了多项式的加法和乘法,因为这两个运算在插值过程中大量使用。

类中最后一个操作是重载了()运算符,该操作是计算多项式在x上的值,其实是为了计算最大相对误差和画图之用。

牛顿插值函数的过程大致为:

求出差商表

计算出插值公式

MFC设计过程中关键步骤有二,一为建立菜单供选择等分点数数目之用,在菜单处理函数中设置等分点个数并调用视图类的操作InValidate()使当前画面无效,系统再自动调用OnDraw()重绘图形。

其二为设计OnDraw()函数,该函数为视图类的一个操作用于绘图,用户可以重载,在该函数中,输出插值函数,画出坐标系以及图形。

2.三次样条插值

三次样条插值函数基于以上的多项式类和线性方程组中的追赶法。

整个实现较为简单,在附录一中的Sample.h中。

为了考察插值效果,将样条插值的结果显示在MFC中,整个架构是也是通过菜单来选择等分点的数目,再显示图形及具体函数。

与牛顿插值一起整合在MFC中。

小程序的截图如下:

该图是牛顿插值法N=10时的情况,可通过菜单选择N的值

该图是三次样条插值N=10的情况,可通过菜单选择N的值

结果分析:

牛顿插值法的图如下:

N=2

N=4

N=6

N=8

N=10可以看到以下几点

1.随着N的增大,插值多项式的波动愈发剧烈,最后,除了插值点外,函数形状与原函数形状完全偏离。

此时发生了龙格(Runge)现象。

2.如果仔细观察最大相对误差(图中字太小,最好运行程序看一下)的话,发现误差不断增大,而且增速是变快的。

3.还可以看到,插值多项式只有偶次项,因为原函数函数是偶函数。

4.越偏离原点,插值函数与原函数的偏差越大。

这一点是多项式函数与原函数的性质造成的,原函数随着X的绝对值趋近无穷大而趋向于零,而多项式随着X的绝对值趋近无穷大而趋向于无穷大,所以两者的偏差会随着|X|的变大而变大。

这一点也反映在最大相对误差往往出现的靠近与?

1的地方。

由此看出,多项式插值时不宜选取次数太高的多项式,为了避免Runge现象,有效途径之一就是分段插值,其中效果比较好的是三次样条插值。

三次样条插值的图如下:

N=10

从上方五张图可以看到随着N的增大,样条插值多项式越来越接近原函数,到N=10的时候,两条曲线几乎难以分辨。

如果运行程序仔细看的话,最大相对误差也是逐渐趋向于零,实际上当N=10的时候,最大相对误差为0.033左右。

但是插值公式也越来越复杂,不易使用。

}

{v[i]=0.5/(2-0.5*v[i]);

u[i]=(d[i]-u[i-1]*0.5)/(2-0.5*v[i-1]);

for(inti=n-1;

ii--)m[i]=u[i]-v[i]*m[i+1];

m=dfp(low);

m[n]=dfp(up);

for(inti=1;

ii++){polynomialtemp(0,fp(low+h*i-h)/h/h/h);

temp*=(polynomial(0,-(low+h*i))+polynomial(1,1));

temp*=(polynomial(1,2)+polynomial(0,h-2*(low+h*i-h)));

S[i]+=temp;

temp=polynomial(0,fp(low+h*i)/h/h/h);

temp*=(polynomial(0,-(low+h*i-h))+polynomial(1,1));

temp*=(polynomial(1,-2)+polynomial(0,h+2*(low+h*i)));

temp=polynomial(0,m[i-1]/h/h);

temp*=(polynomial(1,-1)+polynomial(0,low+h*i));

temp*=(polynomial(1,1)+polynomial(0,-(low+h*i-h)));

temp=polynomial(0,m[i]/h/h);

temp*=(polynomial(1,1)+polynomial(0,-(low+h*i)));

MFC

voidCMFCView:

OnDraw(CDC*pDC){CMFCDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

if(!

pDoc)return;

if(Newton){polynomialp1;

p1=Newton_interpolation(f2,N,-1,1);

CStringstr;

std:

stringss;

ostringstreamstrm;

strm

TextOutW(0,0,str);

pDC-TextOut(0,25,str2);

pDC-SetTextColor(RGB(255,0,0));

str3.Format(L\最大相对误差在X=%f或%f时取得,RelativeError=%f\,p,-p,max);

pDC-TextOut(0,50,str3);

/p1;

>

pDC-SetTextColor(RGB(0,0,0));

CRectrect;

GetClientRect(rect);

pDC-SetViewportOrg(rect.Width()/2,rect.Height()*3/4);

CRectrect1(420,110,-420,-410);

pDC-Rectangle(rect1);

pDC-MoveTo(-420,0);

pDC-LineTo(420,0);

pDC-MoveTo(0,110);

pDC-LineTo(0,-410);

for(doubled=-1;

dd+=0.1){intposx=d*400,posy=0;

pDC-MoveTo(posx,posy);

pDC-LineTo(posx,posy+4);

str.Format(L\,d);

pDC-TextOutW(posx,posy+6,str);

for(doubled=-0.5;

dd+=0.1){if(abs(d)0.01){intposx=0,posy=-200*d;

pDC-LineTo(posx+4,posy);

pDC-TextOutW(posx+6,posy,str);

}}

CPenredpen,bluepen,greenpen;

CBrushgreenbrush;

redpen.CreatePen(PS_SOLID,2,RGB(255,0,0));

bluepen.CreatePen(PS_SOLID,2,RGB(0,0,255));

greenpen.CreatePen(PS_SOLID,1,RGB(0,255,0));

greenbrush.CreateSolidBrush(RGB(0,255,0));

pDC-SelectObject(redpen);

doublex,y;

for(inti=0;

ii++){x[i]=-1+0.02*i;

y[i]=-200/(1+25*x[i]*x[i]);

x[i]*=400;

pDC-MoveTo(x,y);

ii++){pDC-LineTo(x[i],y[i]);

pDC-MoveTo(x[i],y[i]);

pDC-SelectObject(bluepen);

y[i]=-200*p1(x[i]);

}pDC-SelectObject(greenpen);

pDC-SelectObject(greenbrush);

for(doubleh=2.0/N,d=-1;

d1.05;

d+=h){intposx=400*d,posy=-200*f2(d);

pDC-Ellipse(CRect(posx-3,posy-3,posx+3,posy+3));

}}else{CStringstr;

doubleh=2.0/N;

str.Format(L\当N=%d时三次样条的各段插值函数为\,N);

pDC-TextOutW(0,0,str);

vector

S(N+1);

Sample(f2,df,N,-1,1,S);

ii++){std:

strm<

s[i];

ss="

strm.str();

"

cstringstr2(ss.c_str());

str2.appendformat(l\其中x∈[%3.2f,%3.2f]\,-1+h*i-h,-1+h*i);

pdc->

TextOut(0,20*i,str2);

}CRectrect;

pDC-SetViewportOrg(rect.Width()/2+250,rect.Height()*3/4);

}for(doubled=-0.5;

}}CPenredpen,bluepen,greenpen;

/s[i];

/polynomial>

doublemaxpos=-1,maxerr=0,temp;

temp=S[i*N/101+1](x[i]);

if(abs(temp-f2(x[i]))/f2(x[i])maxerr){maxpos=x[i];

maxerr=abs(temp-f2(x[i]))/f2(x[i]);

}y[i]=-200*temp;

pDC-SelectObject(greenpen);

pDC-SetViewportOrg(0,20*N+20);

str.Format(L\最大相对误差在\);

str.AppendFormat(L\或%4.2f时取得,为%f\,maxpos,-maxpos,maxerr);

Matrix.h

#pragmaonce

#include<

iostream>

cmath>

iomanip>

template<

classt>

classMatrix<

/class>

/iomanip>

/cmath>

/iostream>

{

private:

T**mat;

introw;

intcolumn;

//usedindestructorandassignmentoperatorvoiddestroy();

//constructordestructorandassignment//defaultconstructorMatrix():

mat(NULL),row(0),column(0){};

//constructan*nidentitymatrixexplicitMatrix(intn);

//constructam*nzeromatrixMatrix(intm,intn,Tdef=0);

//copyconstructorMatrix(constMatrix//assignmentoperatorMatrixoperator=(constMatrix//destructor~Matrix(){destroy();

};

//miscellaneousprocedures//returnthenumberofrowintRow(){returnrow;

}//returnthenumberofcolumnintColumn(){returncolumn;

}//returnthereferenceofM[m][n].Thiskindofgrammarislikematlab.Toperator()(intm,intn);

//overloadtheostreamtemplate<

classtype>

friendstd:

ostreamoperator(std:

ostreamos,Matrix<

type>

h);

};

/type>

template<

voidMatrix<

t>

:

destroy(){if(mat!

=NULL){for(inti=0;

i<

row;

i++){delete[]mat[i];

}mat;

row="

0;

column="

p>

<

/row;

i++)>

/t>

Matrix<

Matrix(intn):

mat(NULL),row(0),column(0){if(n=0)std:

cerr\<

std:

endl;

else{mat="

new"

t*[n];

for(inti="

i<

n;

i++)"

mat[i]="

t[n];

mat[i][i]="

1;

}<

/std:

i++)for(intj="

j<

j++)"

if(i!

="

j)"

mat[i][j]="

/n;

Matrix(intm,intn,Tdef):

mat(NULL),row(0),column(0){if(m0n0){row=m;

column=n;

mat=newT*[m];

m;

i++)mat[i]="

j="

def;

/m;

Matrix(constMatrixM):

mat(NULL),row(0),column(0){if(M.mat!

=NULL){mat=newT*[M.row];

m.row;

i++){mat[i]="

t[m.column];

for(intj="

M.column;

M.mat[i][j];

}row="

M.row;

/m.row;

operator=(constMatrixM){if(this!

=M){destroy();

if(M.mat!

elsemat="

NULL;

column=0;

}}retur

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

当前位置:首页 > 解决方案 > 学习计划

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

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