Lagrange插值法與Newton插值法

Lagrange插值法

  考慮有nn不同的點 (x1,y1),(x2,y2),(xi,yi)(xn,yn){(x_1,y_1),(x_2,y_2),(x_i,y_i)\dots (x_n,y_n)} ,定義函數fi(x)f_i(x)滿足在li(xj)l_i(x_j)滿足克羅內克符號函數 δij\delta_{ij}
li(xj)=δij={1i=j0ijl_i(x_j)=\delta_{ij}=\begin{cases}1\quad\quad\quad i=j\\0\quad\quad\quad i\not=j\end{cases}

此時,若另L(x)=i=1nyili(x)L(x)=\sum_{i=1}^n y_il_i(x)
則對於任意xix_i
yi=li(xi)y_i=l_i(x_i)
nn個點必然經過L(x)L(x),即爲所求。

  再考慮li(x)l_i(x),其應爲一個n1n-1次多項式,則可由因式法寫出滿足要求的函數:
li(x)=(xx1)(xx2)(xx3)(xxi1)(xxi+1)(xixn)(xix1)(xix2)(xix3)(xixi1)(xixi+1)(xixn)=ji1jnxxjxixj\begin{aligned} l_i(x)&=\frac{(x-x_1)(x-x_2)(x-x_3)\dots(x-x_{i-1})(x-x_{i+1})\dots(x_i-x_n)}{(x_i-x_1)(x_i-x_2)(x_i-x_3)\dots(x_i-x_{i-1})(x_i-x_{i+1})\dots(x_i-x_n)}\\ \\ &=\prod_{j\not=i}^{ 1\le j \le n }\frac{x-x_j}{x_i-x_j} \end{aligned}

這裏的li(x)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插值法

  該方法確定了一組新的基函數,確保能加入新的點能夠重用之前的計算結果:
ϕ1(x)=1ϕ2(x)=(xx1)ϕ3(x)=(xx1)(xx2)=ϕn+1(x)=i=1n(xxi) \begin{aligned} \phi_{1}(x) &=1 \\ \phi_{2}(x) &=\left(x-x_{1}\right) \\ \phi_{3}(x) &=\left(x-x_{1}\right)\left(x-x_{2}\right) \\ \cdots &=\cdots \\ \phi_{n+1}(x) &=\prod_{i=1}^{n}\left(x-x_{i}\right) \end{aligned}
可以看到由於ϕn+1(x)=ϕn(x)(xxn)\phi_{n+1}(x)=\phi_{n}(x)(x-x_{n}),因此可以重用之前的結果。

則最終的多項式爲:
N(x)=i=1n+1aiϕi(x) N(x)=\sum_{i=1}^{n+1}a_i\phi_i(x)
現在僅僅需要確定aia_i的值就可以確定N(x)N(x)

  我們將每個點依次帶入相減可得到一個神奇的規律:
a1=y1a2=y2y1x2x1a3=y3y2x3x2y2y1x2x1x3x1 \begin{aligned} a_1&=y_1\\ a_2&=\frac{y_2-y_1}{x_2-x_1}\\ a_3&=\frac{\frac{y_3-y_2}{x_3-x_2}-\frac{y_2-y_1}{x_2-x_1}}{x_3-x_1}\\ \vdots \end{aligned}
我們把這種叫做差商,0階均差定義爲f[xi]=f(xi)f[x_i]=f(x_i),n1n-1階差商爲:

f[x1,x2,x3xn]=f[x1,x2,x3xn1]f[x2,x3,x4xn]xnx1 f[x_1,x_2,x_3\dots x_n]=\frac{f[x_1,x_2,x_3\dots x_{n-1}]-f[x_2,x_3,x_4\dots x_n]}{x_n-x_1}
下面是差商表,每次迭代也可重用上一步的結果
在這裏插入圖片描述
所以最終爲
N(x)=f(x1)+f[x1,x2](xx1)+f[x1,x2,x3](xx1)(xx2)+f[x1,,x4](xx1)(xx2)(xx3)+ \begin{aligned} N(x)=& f\left(x_{1}\right)+\\ & f\left[x_{1}, x_{2}\right]\left(x-x_{1}\right)+\\ & f\left[x_{1}, x_{2}, x_{3}\right]\left(x-x_{1}\right)\left(x-x_{2}\right)+\\ & f\left[x_{1}, \ldots, x_{4}\right]\left(x-x_{1}\right)\left(x-x_{2}\right)\left(x-x_{3}\right)+\\ & \ldots \end{aligned}

  以下是代碼,可想而知,雖然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");
}

​ 如果要新增節點,可以增量更新差商表

兩者關係

  其實我們可以發現兩個方法都是通過nn個點確定了一組nn個方程的方程組:
{y1=a0+a1x1+a2x12++anx1ny2=a0+a1x2+a2x22++anx2nyn=a0+a1xn+a2xn2++anxnn \begin{cases} y_1&=a_0+a_1x_1+a_2x_1^2+\dots+a_nx_1^n\\ y_2&=a_0+a_1x_2+a_2x_2^2+\dots+a_nx_2^n\\ \vdots\\ y_n&=a_0+a_1x_n+a_2x_n^2+\dots+a_nx_n^n\\ \end{cases}
矩陣形式爲Y=XAY=XA
[y1y2yn]=[1x1x12x1n1x2x22x2n1xnxn2xnn][a0a1an] \begin{bmatrix} y_1\\y_2\\ \vdots \\y_n\end{bmatrix}= \begin{bmatrix} 1&x_1&x_1^2&\dots&x_1^n\\1&x_2&x_2^2&\dots&x_2^n\\ \vdots&\vdots&\vdots&\dots&\vdots\\1&x_n&x_n^2&\dots&x_n^n\end{bmatrix} \begin{bmatrix} a_0\\a_1\\ \vdots \\a_n\end{bmatrix}
  係數矩陣XX爲範德蒙行列式,則X0|X|\not =0,因此可以得出其解AA唯一,故最終確定的多項式唯一,即兩者等效.Largrane法較爲簡單,而Newton法在需要新增節點時可以保持很好的效率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章