计算方法实验指导书彭彬计算机技术实验中心2012年3月· 实验环境: VC++ 6.0· 实验要求:在机房做实验只是对准备好的实验方案进行验证,因此上机前要检查实验准备情况,通过检查后方可上机。
没有认真准备的学生不能上机,本次实验没有分数。
实验中要注意考察和体会数值计算中出现的一些问题和现象:误差的估计,算法的稳定性、收敛性、收敛速度以及迭代初值对收敛的影响等。
· 关于计算精度:如果没有特别说明,在计算的过程中,小数点后保留5位数字,最后四舍五入到小数点后四位数字。
迭代运算的结束条件统一为51102-⨯。
在VC++ 6.0中,可使用setprecision 在流的输出中控制浮点数的显示(缺省显示6位)。
演示如下: # include<iostream.h> # include<math.h> # include<iomanip.h>//输出6位精度,输出左对齐cout<<setprecision(6)<<setiosflags(ios::left); //设置输出宽度为12(不够将补充0) cout<<setw(12)<<coeff[i];· 关于图形绘制本课程个别实验要求画出函数的曲线,所有画图题目均要求用MFC 完成。
利用VC++6.0的MFC 画图,先要建立一个工程,然后在***View 中加入自定义变量、自定义函数等,最后在OnDraw ()方法中调用自定义函数。
也可以把代码直接写入OnDraw ()方法中。
画曲线有两种方法,(一)一句坐标逐个打点(用SetPixel()函数),(二)先把当前光标移动(MoveTo ()函数)到曲线的始点,再用LineTo ()函数画线。
线的样式由画笔决定。
对封闭区域可以填充,填充的样式由画刷决定。
在VC++6.0中,先新建一个MFC AppWizard(exe)类型的工程(建立工程时,“应用程序类型”选择“单文档”;“是否包含数据库”选择“不包含数据库”;其它选择缺省),然后在“ClassView ”中选择XXView 类文件加以操作。
图1是一个名为test 的工程,在CtestView 节点,点击右键,用户可以增加自定义变量,自定义函数。
图1 MFC工程图2是一个自定义函数的例子,代码如下:void CTestView::drawOldLine(int N, CDC *pDC) //N—画线所用点的数目{pDC->TextOut(250,10,"龙格现象");//文本输出//设置画笔,将影响画线的样式CPen *pnewPen,*poldPen;pnewPen=new CPen();pnewPen->CreatePen(PS_SOLID,10,RGB(0,0,0));poldPen=pDC->SelectObject(pnewPen);//画坐标系pDC->MoveTo(0,380); pDC->LineTo(640,380);pDC->MoveTo(320,0); pDC->LineTo(320,480);//画曲线,先移动到本曲线的第一个点pDC->MoveTo(20,380);for(int i=0;i<=N;i++){//原始坐标float x0=-1+2.0/N*i;float y0=1.0/(1+4*x0*x0);//坐标放大x0=x0*300;y0=-y0*300;//坐标转化为整型int x1=(int)(320+x0);int y1=(int)(440+y0);pDC->LineTo(x1,y1);}//重置画笔pDC->SelectObject(poldPen);}图 2 自定义函数画函数21()14f x x=+的图形图3是一个根据Lagrange 插值多项式求函数值的自定义函数Lagrange(float x, int n, float x1[], float y1[]),其中n 是插值节点的个数,数组X1,y1存放插值节点的坐标,x 是待求点的x 坐标,函数根据插值多项式返回对应的y 坐标。
float CTestView::Lagrange(float x, int n, float x1[], float y1[]) {float y=0;//存放函数值int k=0;//控制变量,求lagrange 基函数的值 for( k=0;k<n;k++) { float t=1; for (int j=0;j<n;j++) { if (j!=k) t=t*(x-x1[j])/(x1[k]-x1[j]); } y=y+t*y1[k]; }return y; }图3 自定义函数,根据插值多项式求值图4是onDraw 函数,这是MFC 画图的主要部分。
相关代码如下: void CTestView::OnDraw(CDC* pDC) { CTestDoc* pDoc = GetDocument();//画原始图形drawOldLine(2000,pDC);float px[11],py[11];图4 OnDraw()函数的内容//N--N等分for(int N=2;N<=10;N=N+2){//求插值节点for(int i=0;i<=N;i++){px[i]=-1+2.0/N*i;py[i]=1.0/(1+4*px[i]*px[i]);}//移动到第一个点pDC->MoveTo(20,380);//设置画笔CPen *pnewPen,*poldPen;pnewPen=new CPen();pnewPen->CreatePen(PS_DASHDOT,1+N/2,RGB(255-20*N,0+10*N,20*N));poldPen=pDC->SelectObject(pnewPen);//按照插值节点求插值多项式的值,并描点for(int k=0;k<=2000;k++){float x=-1+2.0/2000*k;float y=Lagrange(x,N+1,px,py);//注意N+1个节点//坐标变换x=x*300;//转化为整型int x1=(int)(320+x);int y1=(int)(440+y);if (N==2 && x1==80)pDC->TextOut(x1,y1,"二等分"); if (N==4 && x1==50)pDC->TextOut(x1,y1,"四等分");if (N==6 && x1==60)pDC->TextOut(x1,y1,"六等分");if (N==8 && x1==580)pDC->TextOut(x1,y1,"八等分");if (N==10 && x1==600)pDC->TextOut(x1,y1,"十等分");pDC->LineTo(x1,y1);}//重置画笔pDC->SelectObject(poldPen);}}实验项目一览表实验一 一元非线性方程求根的算法【实验性质】综合性实验。
【实验目的】了解非线性方程求根的基本方法;掌握二分法和牛顿法。
【实验内容】选择合适的初值,用二分法和牛顿迭代法求出一元非线性方程3()sin 41f x x x x =--+的全部实根,610ε-=。
【理论基础】数值法求非线性方程的跟一般分三步: ① 判定根的存在性; ② 确定根的分布范围 ③ 根的精确化常用的数值方法有二分法和迭代法。
二分法的基本思想是:先确定有根区间,然后通过逐步缩小(二分区间)有根区间的长度,以求根的近似值。
二分法只能求实根,不能求复根及重根。
迭代法通过建立一个迭代序列来逼近根。
迭代效果与迭代初值、迭代公式的收敛性有关。
迭代初始值一般根据高等数学的知识或作图的方法来确定;迭代公式通过对已知方程的某种变换得到。
迭代的收敛性以及收敛速度不仅与迭代公式有关,可能还与迭代初值有关。
牛顿迭代是常用的迭代方法。
把()f x 在k x 处按泰勒公式展开为:()()k f x f x =+2()()()()2!...k k k f f x x x x x ξ'''-+-+,忽略高次项,得到()()()()k k k f x f x f x x x '≈+-。
如果x *是方程的根,则有:()()()()0k k k f x f x f x x x *'≈+-≈由此得:()()k k k f x x x f x *=-' 从而建立起牛顿迭代公式: 1()()k k k k f x x x f x +=-'当相邻两次迭代结果满足1k k x x ε+-≤时停止计算。
如果非线性方程为一元多项式方程,则其牛顿解法的关键在于求()k f x 与()k f x ',这时可以用如下的快速算法(秦九韶算法)。
设n 次多项式()f x 为:0111()...n n n n f x a x a x a x a --=++++1n -次多项式()Q x 为:01121()...n n n n Q x b x b x b x b ---=++++如果()f x 、()Q x 满足()()()k n f x x x Q x b =-+ (1)则有()k n f x b =于是求()k f x 就转换为求系数n b 。
将式(1)展开,有如下递推关系:00b a =⎧⎨因此可以用上述递推公式求出n b ,从而计算出()k f x 。
同理,设2n -次多项式01132()...n n n n H x c x c x c x c ---=++++满足1()()()k n Q x x x H x c -=-+ (2)则有()()()()k f x x x Q x Q x ''=-+1()()k k n f x Q x c -'==由(2)式有递推关系:0001,1,2,...,1ii i k c b a c b c x i n -==⎧⎨=+=-⎩ 因此求()k f x '可以用上式递推计算。
【实验过程】1. 手工或用MFC 画出3()sin 41f x x x x =--+的图形。
【MFC 画图代码】2.估计三个有根区间,用二分法求出三根,并用下述样式的表描述求根过程。