C++ 实现全区间上的n阶拉格朗日插值多项式、分段线性插值式和三次样条插值式(第一种边界条件)(附源码)

已经知道函数y=e^(-2x),对应区间为[0, 6]

把区间n等分,给定各结点上的函数值。编写下列插值函数的程序:

... 打字好慢, 看图


大概就是这样:

下面解题:

1.1 全区间上的n阶拉格朗日插值多项式

      

//对应的算法表述为:
for (int k = 0; k < n; k++) {
		xi = x[k];
		for (int i = 0; i < n; i++)
		{
			ln[i] = 1.0;
			for (int j = 0; j < n; j++)
			{
				if (i == j)
					continue;
				ln[i] *= ((xi - standX[j]) / (standX[i] - standX[j]));
			}
			res[k] += (standY[i] * ln[i]);
		}
	}

1.2  分段线性插值式

      

      

//对应的算法表述为:

for (int j = 0; j < n; j++) {
		xm = x[j];

		for (int i = 0; i<n; i++)
		{
			if (standX[i] <= xm && xm <= standX[i + 1])
			{
				ym[j] = (standY[i] * ((xm - standX[i + 1]) / (standX[i] - standX[i + 1])) + standY[i + 1] * ((xm - standX[i]) / (standX[i + 1] - standX[i])));
				cout << ym[j] << " ";
				break;
			}
			else {
				continue;
			}
		}
	}

1.3 三次样条插值式(第一种边界条件)

      实际应用中,很多情况都需要有二阶光滑度,即具有二阶连续微商,但是分段线性插值的一阶微商并不连续,所以为了保证插值函数及其导数,在插值区间上处处充分接近被插值函数,需要样条函数作插值函数。

为了构造三次样条插值函数,我们需要给定区间[a, b]上的n+1个点,使得插值函数在每一个小的区间上都是一个三次多项式,构造三次样条插值函数的过程如下:


double * spl2(
	int n,						/*输入数据个数*/
	double x[],					/*x坐标序列*/
	double y[],					/*y坐标序列*/
	double ddy1, double ddyn,	/*第一点和最末点二阶导数*/
	double t[],					/*插值点的x坐标序列*/
	int m                      /*插值点个数*/
)
{
	cout << endl << "三次样条..." << endl;
	int i, j;
	double h0, h1, alpha, beta, *s, *dy;
	double z[1000];
	s = new double[n];
	dy = new double[n];
	dy[0] = -0.5;
	h0 = x[1] - x[0];
	s[0] = 3.0*(y[1] - y[0]) / (2.0*h0) - ddy1*h0 / 4.0;
	for (j = 1; j <= n - 2; j++)
	{
		h1 = x[j + 1] - x[j];
		alpha = h0 / (h0 + h1);
		beta = (1.0 - alpha)*(y[j] - y[j - 1]) / h0;
		beta = 3.0*(beta + alpha*(y[j + 1] - y[j]) / h1);
		dy[j] = -alpha / (2.0 + (1.0 - alpha)*dy[j - 1]);
		s[j] = (beta - (1.0 - alpha)*s[j - 1]);
		s[j] = s[j] / (2.0 + (1.0 - alpha)*dy[j - 1]);
		h0 = h1;
	}
	dy[n - 1] = (3.0*(y[n - 1] - y[n - 2]) / h1 + ddyn*h1 / 2.0 - s[n - 2]) / (2.0 + dy[n - 2]);
	for (j = n - 2; j >= 0; j--)        
		dy[j] = dy[j] * dy[j + 1] + s[j];
	for (j = 0; j <= n - 2; j++)        
		s[j] = x[j + 1] - x[j];
	cout << "y: " << endl;
	for (j = 0; j <= m - 1; j++)
	{
		if (t[j] >= x[n - 1]) i = n - 2;
		else
		{
			i = 0;
			while (t[j]>x[i + 1]) i = i + 1;
		}
		h1 = (x[i + 1] - t[j]) / s[i];
		h0 = h1*h1;
		z[j] = (3.0*h0 - 2.0*h0*h1)*y[i];
		z[j] = z[j] + s[i] * (h0 - h0*h1)*dy[i];
		h1 = (t[j] - x[i]) / s[i];
		h0 = h1*h1;
		z[j] = z[j] + (3.0*h0 - 2.0*h0*h1)*y[i + 1];
		z[j] = z[j] - s[i] * (h0 - h0*h1)*dy[i + 1];
		cout << z[j] << " ";

	}
	delete[] s;
	delete[] dy;
	return z;
}
 
 

5.    使用说明

使用VS 2015或者更高版本的编辑器打开sln文件,运行即可,程序运行结果将保存在D:\result.txt文件中

6.    算例结果及分析

当插值点为20个的时候:

当插值点为30个的时候


程序源码参见:链接

或者:https://download.csdn.net/download/wql2014302721/10331108


参考文章:

https://blog.csdn.net/twicave/article/details/2808038

https://blog.csdn.net/shaguabufadai/article/details/53026626

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tailor_long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值