已经知道函数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;
}
![](https://i-blog.csdnimg.cn/blog_migrate/0802bbaca14c2090b6c54950b0996dba.jpeg)
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