艾特肯逐步插值法

艾特肯(Aitken)逐步插值算法是代数插值中一个较为普遍的算法,对于拉格朗日插值,误差的余项并不能判断大小,而艾特肯插值法解决了余项的精度问题,该方法可以通过精度的要求逐步提高插值的阶,在插值过程中只需要通过两个低阶的插值结果进行线性拟合即可,并且计算方便。
具体实现过程就不多说了,我在代码里面注释的很清楚了!
代码如下:

//全区间艾特肯插值
//函数接口说明:
/* double  Aitken(double* x,double *y ,int n,double t,double accu)
 * x为输入数组指针,代表插值的横坐标集合
 * y为输入数组指针,对应x中横坐标相对应的纵坐标的值
 * n为插值结点的个数
 * t为插值点的值
 * accu是插值的精度要求
 * 函数的返回值是double类型的,返回该插值结点对应的纵坐标
*/



#include<iostream>
#include<cmath>
using namespace std;

double Aitken(double* x, double* y, int n, double t, double accu)
{
    int i, j, k;                                                              //循环变量
    int m=10;                                                                 //定义最大插值点的个数10
    int l;                                                                    //二分查找的中间变量
    double xx[10], yy[10];                                                    //存放线性插值的中间数组,由于最多10个点,所以大小为10
    if (n < 1)  throw("the number of point is less than 1");                   //少于一个点,就抛出异常
    if (n == 1)   return y[0];                                                 //一个点,直接返回该点的值

    if (m > n) m = n;                                                          //判断点的个数,少于10个,就把插值点的值赋给m
    //寻找最接近t的点
    if (t <= x[0]) k = 1;                                                       //如果插值点t在结点最左边,插值区间下限为1
    else if (t >= x[n - 1]) k = n;                                              //在右边,插值区间上限为n
    else
    {
        k = 1; j = n;                                                          //在中间,用二分查找那个点
        while ((k - j != 1) && (k - j != -1))
        {
            l = (k + j) / 2;
            if (t < x[l - 1])
                j = l;
            else
                k = l;
        }
        if (fabs(t - x[l - 1]) > fabs(t - x[j - 1]))
            k = j;
    }


    //从中心位置k寻找参加插值的结点
    j = 1; l = 0;
    for (i = 1; i <= m; i++)                                                    //该方法挑出中间点的元素,分别是k的左边一个、右边一个
    {
        k = k + j*l;
        if ((k < 1) || (k > n))                                             //如果是左边或者右边没数了,就用这个挑出右边或左边的数
        {
            l = l + 1;
            j = -j;
            k = k + j*l;
        }
        xx[i - 1] = x[k - 1];
        yy[i - 1] = y[k - 1];
        l = l + 1;
        j = -j;
    }




//进行艾特肯逐步线性插值                                                                    
/*该插值先计算xx[0],xx[1],得出结果放在yy[1]中
 *接下来计算xx[0],xx[2],得出结果z,并继续计算yy[1]和z的值,存放在yy[2]中。
 *依次类推
 *yy[10]数组中存放的永远是插值的计算的对角线的元素(列出插值表可以看出)
*/
    i = 0;
    double z;
    do
    {
        i = i + 1;
        z = yy[i];
        for (j = 0; j <= i - 1; j++)
            z = yy[j] + (t - xx[j])*(yy[j] - z) / (xx[j] - xx[i]);                         //艾特肯逐步线性插值公式

        yy[i] = z;
    } while ((i != m - 1) && (fabs(yy[i] - yy[i - 1]) > accu));
        return z;
}




int main()
{
    double x[11] = { -1.0,-0.8,-0.65,-0.4,-0.3,0.0,0.2,0.4,0.6,0.8,1.0 };
    double y[11] = { 0.0384615,0.0588236,0.0864865,0.2,0.307692,1.0,0.5,0.2,0.1,0.0588236,0.0384615 };
    //double x[5] = { 0.3,0.4,0.5,0.6,0.7 };
    //double y[5] = { 0.29850,0.39646,0.49311,0.58813,0.58122 };

    double accu = 1.0e-8;
    double t = -0.75;
    double c;
    c = Aitken(x, y, 11, t, accu);
    cout << "  " << c << endl;
    t = 0.05;
    c = Aitken(x, y, 11, t, accu);
    cout << "   " << c << endl;
    return 0;
}


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值