插值(三)——Newton插值(C++)

差商

对于一系列互不相等的 x 0 , x 1 , ⋯   , x n x_0,x_1,\cdots,x_n x0,x1,,xn,有差商定义如下:
f [ x i , x j ] = f ( x i ) − f ( x j ) x i − x j ( i ≠ j , i , j = 0 , 1 , ⋯   , n ) f[x_i,x_j]=\frac{f(x_i)-f(x_j)}{x_i-x_j}(i\neq j,i,j=0,1,\cdots,n) f[xi,xj]=xixjf(xi)f(xj)(i=j,i,j=0,1,,n)
称此为 f ( x ) f(x) f(x) x i , x j x_i,x_j xi,xj处的一阶差商,又称
f ( x i , x j , x k ) = f [ x i , x j ] − f [ x j , x k ] x i − x k f(x_i,x_j,x_k)=\frac{f[x_i,x_j]-f[x_j,x_k]}{x_i-x_k} f(xi,xj,xk)=xixkf[xi,xj]f[xj,xk]
f ( x ) f(x) f(x) x i , x j , x k x_i,x_j,x_k xi,xj,xk处的二阶差商。
因此可以得到n阶差商的定义:
f [ x 0 , x 1 , ⋯   , x n ] = f [ x 0 , x 1 , ⋯   , x n − 1 ] − f [ x 1 , x 2 , ⋯   , x n ] x 0 − x n f[x_0,x_1,\cdots,x_n]=\frac{f[x_0,x_1,\cdots,x_{n-1}]-f[x_1,x_2,\cdots,x_n]}{x_0-x_n} f[x0,x1,,xn]=x0xnf[x0,x1,,xn1]f[x1,x2,,xn]
差商的计算方法如下:
插值(三)——Newton插值(C++)_第1张图片

牛顿插值法

与拉格朗日插值法不同,如果需要增加插值点,拉格朗日插值法需要重新计算所有插值点的值,重新计算基函数,而牛顿插值法只需要重附上一项即可,不需要重新计算。
牛顿插值法需要利用到差商,其插值公式如下:
N n ( x ) = f ( x 0 ) + f [ x 0 , x 1 ] ∗ ( x − x 0 ) + f [ x 0 , x 1 , x 2 ] ∗ ( x − x 0 ) ( x − x 1 ) + f [ x 0 , x 1 , x 2 , x 3 ] ∗ ( x − x 0 ) ( x − x 1 ) ( x − x 2 ) + ⋯ + f [ x 0 , x 1 , ⋯   , x n ] ∗ ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 1 ) \begin{aligned} N_n(x)=&f(x_0)+f[x_0,x_1]*(x-x_0)+f[x_0,x_1,x_2]*(x-x_0)(x-x_1)+\\&f[x_0,x_1,x_2,x_3]*(x-x_0)(x-x_1)(x-x_2)+\cdots +\\&f[x_0,x_1,\cdots,x_n]*(x-x_0)(x-x_1)\cdots(x-x_{n-1}) \end{aligned} Nn(x)=f(x0)+f[x0,x1](xx0)+f[x0,x1,x2](xx0)(xx1)+f[x0,x1,x2,x3](xx0)(xx1)(xx2)++f[x0,x1,,xn](xx0)(xx1)(xxn1)

代码

//牛顿插值法
#include
#include
//求差商
void poor_quotient(double *xi,double *yi,double *Ni,int n)
{
    double **a_temp=new double*[n];
    for (int i=0; i < n;i++)
    {
        a_temp[i]=new double[n];
        a_temp[i][0]=yi[i];
    }
    for (int j = 1; j < n;j++)
    {
        for (int i=j; i < n;i++)
        {
            a_temp[i][j]=(a_temp[i][j-1]-a_temp[i-1][j-1])/(xi[i]-xi[i-j]);
        }
    }
        for (int i = 0; i < n; i++)
        {
            Ni[i] = a_temp[i][i];
        }
    for (int i = 0; i < n;i++)
    {
        delete[] a_temp[i];
    }
    delete[] a_temp;
}
double Newton(double *Ni,double *xi,double x,int n)
{
    double result =Ni[0];
    double temp = 1.0f;
    for (int i = 1;i>n;
    double error[3]={0.0f,0.0f,0.0f};//误差评价
    double *x = new double [n];
    double *y = new double [n];
    double *Ni = new double [n];
    double a=3, b=10;//定义插值区间
    //生成插值数据
    for (int i = 0;i error[0])
        {
            error[0] = fabs(y_temp - y_temp2);
            // std::cout << y_temp2 << std::endl;
        }
        error[1] += fabs((y_temp - y_temp2) / y_temp);
        error[2] += ((y_temp - y_temp2)) * ((y_temp - y_temp2));
    }
    //err[0]得到的是在区间内最大的误差
    //err[1]得到的是平均最大相对误差
    //err[2]是均方根误差
    error[1] = error[1]/100;
    error[2] = sqrt(error[2]/100);
    for(int i = 0;i < 3;i++)
    {
        std::cout<<"误差"<

结果分析

与多项式插值、拉格朗日插值相比,对于相同的测试函数,其具有更高的精度,并且其龙格现象也更加不明显。
插值(三)——Newton插值(C++)_第2张图片

在这里插入图片描述

插值(三)——Newton插值(C++)_第3张图片
插值(三)——Newton插值(C++)_第4张图片

你可能感兴趣的:(计算方法,c++,线性代数)