数值分析实验相关

综合说明:

在写这次实验的时候,程序的图形方式选用的是SDL图形库,关于SDL图形库的使用,可以网上查询相关资料,对于一般的2D图形显示还是很简单好上手的。

这些实验的代码我都发在了GitHub:https://github.com/FieldSoft-HelloClyde/NumericalAnalysisExperiment/

也遇到一些问题,我也分享一下解决办法:

1.配置完的SDL项目显示控制台:

需要在项目属性-配置属性-链接器-系统 选项卡中把子系统设置为控制台。

2.VS2012程序不能再XP系统上运行:

首先需要对VS2012打上最新的补丁。访问https://www.visualstudio.com/downloads/download-visual-studio-vs#d-additional-software,选择VS2012更新X(目前是5).

下载安装后项目属性-配置属性-常规选项卡下中的平台工具集可以选择Windows XP相关选项

但是这样往往还不够,可能在XP运行的时侯还会出现缺少msvcp110.dll的问题。

这就需要安装VS2012的运行库

http://www.microsoft.com/zh-cn/download/details.aspx?id=30679

下载安装即可。

3.调试时候遇到程序相对路径不正确的问题

解决方法是在项目属性-配置属性-调试-工作目录 选择生成的程序根目录

4.SDL 鼠标滚轮使用

这里贴一段代码大概就明白了。

while(SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT){
				While_Quit = 4;
			}
			else if (event.type == SDL_MOUSEMOTION){
				if (MoveState){
					int dx,dy;
					dx = event.motion.x - Mouse_Old_X;
					dy = event.motion.y - Mouse_Old_Y;
					X_pos += dx;
					Y_pos += dy;
					Mouse_Old_X = event.motion.x;
					Mouse_Old_Y = event.motion.y;
				}
			}
			else if (event.type == SDL_MOUSEBUTTONDOWN){
				if (event.button.button == SDL_BUTTON_LEFT){
					if (event.motion.x >= 20 && event.button.x <= 65 && event.button.y >= 80 && event.button.y <= 100){
						X_pos = Windows_Width / 2;
						Y_pos = Windows_Height / 2;
						PixRate = 1.0;
					}
					else{
						MoveState = true;
						Mouse_Old_X = event.motion.x;
						Mouse_Old_Y = event.motion.y;
					}
				}
			}
			else if (event.type == SDL_MOUSEBUTTONUP){
				if (event.button.button == SDL_BUTTON_LEFT){
					MoveState = false;
				}
			}
			else if (event.type == SDL_MOUSEWHEEL){
				if (event.wheel.y > 0){
					//放大
					PixRate *= 2;
				}
				else if (event.wheel.y < 0){
					PixRate /= 2;
				}
			}
         }

当y值大于0时表示滚轮向上滚动,小于0表示滚轮向下滚动。

1.Lagrange插值多项式

公式:

关键算法:

double Lagrange_n(double xx){
	double x[] = {0,10,20,30,40,50,60,70,80,90,100,110,120};
	double y[] = {5,1,7.5,3,4.5,8.8,15.5,6.5,-5,-10,-2,4.5,7};
	return Lagrange(13,x,y,xx);
}

double Lagrange(int n,double *x,double *y,double xx){
	double addResult = 0;
	int k = 0;
	for (k = 0;k < n;k ++){
		double mulResult = 1;
		int j = 0;
		for (j = 0;j < n;j ++){
			if (j == k) continue;
			mulResult *= (xx - x[j]) / (x[k] - x[j]);
		}
		addResult += y[k] * mulResult;
	}
	return addResult;
}
其中数组x,y就是测试数据


运算结果:

所画函数就是Ln(x),红点就是测试数据。可能看不清。

2.Newton插值多项式

公式:

其中f[x0,x1,....xn]为差商公式

具体公式为:(来自百度百科)

差商(difference quotient)的定义:
函数f(x)在两个互异点xi,xj处的一阶差商定义为:
f[xi,xj]=[f(xi)-f(xj)]/(xi-xj)=(yi-yj)/(xi-xj)
一阶差商的差商称为函数f(x)在xi,xj,xk(i,j,k互异)点的二阶差商:
f[xi,xj,xk]={f[xi,xj]-f[xj,xk]}/(xi-xk)
一般的,k-1阶差商的差商称为函数f(x)在n+1个互异点x0,x1,...,xk上的k阶差商:
f[x0,x1,...,xk]={f[x0,x1,...,xk-1]-f[x1,x2,...,xk]}/(x0-xk)
特别的,规定零阶差商f[xk]=f(xk)=yk

我们使用递归来定义它。

相关算法:

double Newton_n(double xx){
	double x[] = {0,10,20,30,40,50,60,70,80,90,100,110,120};
	double y[] = {5,1,7.5,3,4.5,8.8,15.5,6.5,-5,-10,-2,4.5,7};
	for (int i = 0;i < 13;i ++){
		for (int j = 0;j < 13;j ++){
			DiffQuoTable[i][j] = 0;
			DiffQuoExist[i][j] = false;
		}
	}
	return Newton(13,x,y,xx);
}

/*
原本效率较低
优化001:
	数组储存临时内容,减少重复计算
*/
double DiffQuotient(double *x,double *y,int xstart,int xx){
	if (DiffQuoExist[xstart][xx]){
		return DiffQuoTable[xstart][xx];
	}
	else{
		if (xx == 1){
			return (y[xstart] - y[xstart + 1]) / (x[xstart] - x[xstart + 1]);
		}
		else if (xx == 0){
			return y[xstart + xx];
		}
		else{
			DiffQuoTable[xstart][xx] = (DiffQuotient(x,y,xstart,xx - 1) - DiffQuotient(x,y,xstart + 1,xx - 1)) / (x[xstart] - x[xstart + xx]);
			DiffQuoExist[xstart][xx] = true;
			return DiffQuoTable[xstart][xx];
		}
	}
}

double Newton(int n,double *x,double *y,double xx){
	double result = y[0];
	int index = 0;
	for (index = 0;index < n - 1;index ++){
		double anresult;
		anresult = DiffQuotient(x,y,0,index + 1);
		int index2 = 0;
		for (index2 = 0;index2 <= index;index2 ++){
			anresult *= (xx - x[index2]);
		}
		result += anresult;
	}
	return result;
}

对于差商算法,只使用递归会导致效率极低。经过分析发现,差商计算过程中有很多中间步骤是重复计算的,于是使用数组来临时储存计算结果,来对其优化。效果很不错。

计算结果:


3.Hermite插值多项式

公式:

算法:

double Hermite_n(double xx){
	double x[] = {0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0};
	double y[] = {0.904837,0.818731,0.740818,0.670320,0.606531,
				0.548812,0.496585,0.449329,0.406570,0.367879};
	double m[] = {-0.904837,-0.818731,-0.740818,-0.670320,-0.606531,
				-0.548812,-0.496585,-0.449329,-0.406570,-0.367879};
	return Hermite(10,x,y,m,xx);
}

double Hermite(int n,double *x,double *y,double *m,double xx){
	double Result = 0;
	for (int j = 0;j < n;j ++){
		double lj = 1;
		for (int i = 0;i < n;i ++){
			if (i == j) continue;
			lj *= (xx - x[i]) / (x[j] - x[i]);
		}
		double ljs = 0;
		for (int k = 0;k < n;k ++){
			if (k == j) continue;
			ljs += (double)1.0 / (x[j] - x[k]);
		}
		double aj;
		aj = (1 - 2 * (xx - x[j]) * ljs) * lj * lj;
		double bj;
		bj = (xx - x[j]) * lj * lj;
		Result += y[j] * aj + m[j] * bj;
	}
	return Result;
}

运算结果:



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课题一: 线性方程组的迭代法 一、实验内容 1、设线性方程组 = x = ( 1, -1, 0, 1, 2, 0, 3, 1, -1, 2 ) 2、设对称正定阵系数阵线方程组 = x = ( 1, -1, 0, 2, 1, -1, 0, 2 ) 3、三对角形线性方程组 = x = ( 2, 1, -3, 0, 1, -2, 3, 0, 1, -1 ) 试分别选用Jacobi 迭代法,Gauss-Seidol迭代法和SOR方法计算其解。 二、实验要求 1、体会迭代法求解线性方程组,并能与消去法做以比较; 2、分别对不同精度要求,如 由迭代次数体会该迭代法的收敛快慢; 3、对方程组2,3使用SOR方法时,选取松弛因子 =0.8,0.9,1,1.1,1.2等,试看对算法收敛性的影响,并能找出你所选用的松弛因子的最佳者; 4、给出各种算法的设计程序和计算结果。 三、目的和意义 1、通过上机计算体会迭代法求解线性方程组的特点,并能和消去法比较; 2、运用所学的迭代法算法,解决各类线性方程组,编出算法程序; 3、体会上机计算时,终止步骤 (予给的迭代次数),对迭代法敛散性的意义; 4、体会初始解 x ,松弛因子的选取,对计算结果的影响。 课题二:数值积分 一、实验内容 选用复合梯形公式,复合Simpson公式,Romberg算法,计算 (1) I = (2) I = (3) I = (4) I = 二、实验要求 1、 编制数值积分算法的程序; 2、 分别用两种算法计算同一个积分,并比较其结果; 3、 分别取不同步长 ,试比较计算结果(如n = 10, 20等); 4、 给定精度要求 ,试用变步长算法,确定最佳步长。 三、目的和意义 1、 深刻认识数值积分法的意义; 2、 明确数值积分精度与步长的关系; 3、 根据定积分的计算方法,可以考虑二重积分的计算问题。 四、流程图设计

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值