上篇文章用了3次拉格朗日插值http://blog.csdn.net/qq_26025363/article/details/53376477,3次插值可能精度不够,如果数据点很密集的话,多次插值可能更好,所以本次编写了通用的插值多项式算法,由于拉格朗日插值插值的精度超过8个点误差就比较大了,所以大于8个点的数据,只取最接近插值点的8个数据。不足8个点的按全区间插值。
下面贴代码:
/*本算法是全区间拉格朗日插值
*由于该算法的稳定性通常是8个点插值,如果超过8个点
*该算法就可能不稳定了。
*插值结果就会有问题。
*函数的输入是一个double节点数组x[n],和一个double值数组y[n],
*还有插值点double t,与插值节点的个数n.
*返回值是double类型
*/
#include<iostream>
#include<iomanip>
using namespace std;
double Lagrange(double* x, double* y, int n, double t)
{
if (n < 0) //如果没有数据点,抛出异常
{
throw("can't use this way,not enough data point!!");
return 0;
}
if (n == 1) return y[0]; //数据点只有一个,直接返回该点
if (n == 2) return ((y[0] * (t - x[1]) - y[1] * (t - x[0])) / (x[1] - x[0]));//2个点就进行线性插值,返回结果
int i = 0;
while ((t > x[i]) &&(t < n)) //寻找插值点的最近位置
i++;
int k = i - 4; //插值点的起始点
if (k < 0) k = 0;
int m = i + 3; //插值点的最后一个点
if (m > n - 1) m = n - 1;
//进行拉格朗日插值计算
double result=0.0;
for (int j = k; j <= m; j++)
{
double s = 1;
for (int l = k; l < m; l++)
if (j != l)
s *= (t - x[l]) / (x[j] - x[l]);
result += y[j] * s;
}
return result; //返回结果
}
int main()
{
double aa = 1.682;
double bb = 1.813;
double c;
double a[5] = { 1.615,1.634,1.702,1.828,1.921 };
double b[5] = { 2.41450,2.46459,2.65271,3.03035,3.34066 };
c = Lagrange(a, b, 5, aa);
cout << setprecision(8) << c << endl; //2.6135
double ff;
ff = Lagrange(a, b, 5, bb); //2.8736393
cout << ff << endl;
double x[10] = { 0.1,0.15,0.25,0.4,0.5,0.57,0.70,0.85,0.93,1.00 };
double y[10] = { 0.904837,0.860708,0.778801,0.670320,0.606531,0.565525,0.496585,0.427415,0.394554,0.367879 };
double t = 0.63;
double z = Lagrange(x, y, 10, t);
cout << "z= " << setprecision(10) << z << endl; //0.528789246
ret
分析,与3个点的拉格朗日比较,8个点的算法的结果是
//对应于上篇算法的那个输入:
t=1.682的时候,全区间插值的结果是2.6135 ; 3点插值的结果是2.5962391
t=1.813的时候,全区间插值的结果是2.8736393;3点插值的结果是2.9828115
//*****************************************
//对应于这次的输入数据:
t=0.63的时候,全区间插值的结果是0.528789246;3点插值的结果是 0.5325412;
可以看出来,这两个算法的结果差距还是挺大的,有0.1左右的误差。
初步分析,跟选取的数据点的个数确实相关,还跟数据点的间距有关,也与插值曲线的光滑程度有关,所以拉格朗日插值还是很局限的!