Lagrange插值法

​ 考虑有$n$个不同的点 , 定义函数满足在满足克罗内克符号函数

此时,若另

则对于任意$x_i$有

即$n$个点必然经过$L(x)$,即为所求。

​ 再考虑$l_i(x)$,其应为一个$n-1$次多项式,则可由因式法写出满足要求的函数:

这里的$l_i(x)$称为插值基函数。

​ 以下是代码实现

#include<stdio.h>
#include<stdlib.h>
float x[7] = {1.20, 1.24, 1.28, 1.32, 1.36, 1.40};
float y1[7] = {1.09545, 1.11355, 1.13137,1.14891, 1.16619, 1.18322};
float y2[7] = {0.07918, 0.09342, 0.10721, 0.12057, 0.13354, 0.14613};
float xi[6] = {1.22, 1.26, 1.30, 1.34, 1.38};

float Lagrange(float *y,float cx)
{
    int n=6;
    float temp[10],ans=0;
    for(int i=0;i<n;i++)
    {
        temp[i] = y[i];
        for(int j=0;j<n;j++)
        if(j!=i)
            temp[i] *= (cx - x[j]) / (x[i] - x[j]);
        ans += temp[i];
    }
    return ans;
}

int main()
{
    for (int i = 0; i < 5;i++)
        printf("当x=%.2f,y1=%.5f,y2=%.5f\n", xi[i], Lagrange(y1,xi[i]),Lagrange(y2,xi[i]));
    system("pause");
    return 0;
}

​ 我们可以发现假如新加入一个点,就必须得重新计算,这是它的缺点.

Newton插值法

​ 该方法确定了一组新的基函数,确保能加入新的点能够重用之前的计算结果:

可以看到由于,因此可以重用之前的结果。

则最终的多项式为:

现在仅仅需要确定$a_i$的值就可以确定$N(x)$。

​ 我们将每个点依次带入相减可得到一个神奇的规律:

我们把这种叫做差商,0阶均差定义为$f[x_i]=f(x_i)$,$n-1$阶差商为:

下面是差商表,每次迭代也可重用上一步的结果

所以最终为

以下是代码,可想而知,虽然Newton插值效率提高了,但是也要多出一部分来计算差商

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
float x[7] = {1.20, 1.24, 1.28, 1.32, 1.36, 1.40};
float y1[7] = {1.09545, 1.11355, 1.13137,1.14891, 1.16619, 1.18322};
float y2[7] = {0.07918, 0.09342, 0.10721, 0.12057, 0.13354, 0.14613};
float xi[6] = {1.22, 1.26, 1.30, 1.34, 1.38};
float diff[10][10];//差商值表
float phi[10];//基函数值
int n=6;

//求差商表,有点像动态规划
void DifferenceQuotient(float *y)
{
  for (int i = 0; i < n;i++)
    diff[i][0] = y[i];
    
  for (int i = 1; i < n;i++)
  {
    for (int j = 1 ; j < i+1;j++)
      diff[i][j] = (diff[i][j - 1] - diff[i-1][j - 1]) / (x[i] - x[i-j]);
  }

}


float Newton(float *y,float cx)
{
  phi[0] = 1;
  float ans = 0;
  for (int i = 1; i < n;i++) //其基函数的值
    phi[i] = phi[i-1]*(cx - x[i-1]);
  
  for (int i = 0; i < n;i++)
    ans += phi[i] * diff[i][i];//多项式求和为最终结果
  
  return ans;
}

int main(){
  DifferenceQuotient(y1);
  for (int i = 0; i < 5;i++)
        printf("当x=%.2f,y1=%.5f\n", xi[i], Newton(y1,xi[i]));

  cout << endl;

  DifferenceQuotient(y2);
  for (int i = 0; i < 5;i++)
        printf("当x=%.2f,y2=%.5f\n", xi[i],Newton(y2,xi[i]));

  system("pause");
}

​ 如果要新增节点,可以增量更新差商表

两者关系

​ 其实我们可以发现两个方法都是通过$n$个点确定了一组$n$个方程的方程组:

矩阵形式为$Y=XA$

系数矩阵$X$为范德蒙行列式,则$|X|\not =0$,因此可以得出其解$A$唯一,故最终确定的多项式唯一,即两者等效.Largrane法较为简单,而Newton法在需要新增节点时可以保持很好的效率。


本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

旋转变换矩阵推导 上一篇
打家劫舍 下一篇