当前位置: 首页 > news >正文

计算方法实验五 插值多项式的求法

【实验性质】

综合性验

【实验目的】

掌握Lagrange插值算法、Newton插值算法;理解Newton插值算法相对于Lagrange插值算法的优点。

【实验内容】

先用C语言自带的系统函数sin x求出 的值,然后分别用Lagrange、Newton方法求出的值,并与用C语言sin x函数计算出的作比较。

【理论基础】

  1. Lagrange插值公式经过n + 1个插值节点(𝑥0, 𝑦0),(𝑥1, 𝑦1),… …,(𝑥𝑛,𝑦𝑛)的n次Lagrange插值多项式为:

【提示:用两个向量分别存放X、Y坐标;设计一个专门求第k个拉格朗日基函数在某点函数值的函数;基函数的个数=点数;累加项的个数=点数】

2.NewTon插值公式经过n1个插值节点(𝑥0, 𝑦0),(𝑥1, 𝑦1),… …,(𝑥𝑛, 𝑦𝑛)的n次Newton插值多项式为:

P𝑛(𝑥) = 𝑓(𝑥0) + 𝑓[𝑥0, 𝑥1](𝑥 − 𝑥0) + ⋯ +f[𝑥0, 𝑥1, … … , 𝑥𝑛](x − 𝑥0)(x − 𝑥1) … … (x − 𝑥𝑛−1) 

上式中插商f[𝑥0, 𝑥1, … … , 𝑥𝑛]的计算常用到如下的Newton差商表:

其中差商是一个递推的定义:

由上表可知:每增加一个插值节点,都需从一阶插商算起。但在具体应用时,有两种方案:

2.1基于两个n+1维的向量进行计算当节点数n+1固定时,使用两个维数为n+1的向量x、y来存放插值计算的中间结果。其中x存放插

值节点的X坐标;y开始存放插值节点的Y坐标,计算过程中存放各阶差商值。

计算差商时,一次计算差商表的一列。计算 f x x[ 0, 1]时用到向量y的第2个元素和第1个元素,计算 f x x[ 1, 2]时用到向量y的第3个元素和第2个元素,不必再用到y的第一个元素,由此可把 f x x[ 0, 1]放到 y的第一个元素上,把 f x x[ 1, 2]放到y 的第2 个元素上,…。计算二阶差商时,把二阶差商放到y[1]、

y[2]、…。这样牛顿插值公式中用到的f[x0]、f[x0,x1]、f[x0,x1,x2]、……,依次均存放在Y[1]上。算法实现参考:

NewTon差商表

【特点:用两个向量处理计算,向量 y 存放差商;每次计算的差商都从 Y 的第一个元素开始存放;】

2.2基于向量+矩阵进行计算考虑动态增加插值结点,比如已有x0,x1,再增加x2时,依次计算f[x1,x2],f[x0,x1,x2]。当增

加第n+1个节点时,用x[n+1]存放该点X坐标,用矩阵y[n+1][1]存放点的Y 坐标,用y[n+1][i+1]存放本行的i阶差商(1≤i≤n),有:

Y(n,i)=(Y的本行前1列―Y的前1行前1列)/(X的本行-?)=(Y(n,i-1)-Y(n-1,i-1))/(x[n]-x[n-(i-1)])

 

【特点:用矩阵存放各阶差商,矩阵的阶数=点的个数】

【实验过程】

1.分别用Lagrange插值和Newton插值求解,要求给出代码与计算结果。

头文件:

#ifndef INTERPOLATIONPOLYNOMIAL_H

#define INTERPOLATIONPOLYNOMIAL_H

#include "colvector.h"

class InterpolationPolynomial

{

public:

    InterpolationPolynomial();

    //求第K个拉格朗日插值基函数在xt处的值

    double LagrangeBaseFunctionValue(ColVector &x,int k,double xt);

    //用拉格朗日插值多项式求xt处的值

    void LagrangeInterpolationValue(ColVector &x,ColVector &y,double xt,int &flag,double &yt);

    //求牛顿差商表,矩阵存放结果,逐行计算

    void  NewtonDifference_1(ColVector &x,ColVector &y,Matrix &n_d);

    //求牛顿差商表,矩阵存放结果,逐列计算

    void  NewtonDifference_2(ColVector &x,ColVector &y,Matrix &n_d);

    //求牛顿差商表,向量存放结果,逐列计算(倒序计算)

    void  NewtonDifference_3(ColVector &x,ColVector &y);

    //用牛顿插值多项式求xt处的值

    void NewtonInterpolationValue(ColVector &x,ColVector &y,double xt,int &flag,double &yt);

};

#endif // INTERPOLATIONPOLYNOMIAL_H

主函数:

 //实验五

#include <iostream>

#include <windows.h>

#include "colvector.h"

#include "matrix.h"

#include <windows.h>

#include "linearequations.h"

#include "interpolationpolynomial.h"

using namespace std;

int main()

{

    SetConsoleOutputCP(CP_UTF8);

    cout<<"=============牛顿插值多项式============="<<endl;

    double a1[]={0,M_PI/6,M_PI/4,M_PI/3,M_PI/2};

    double b1[]={sin(0),sin(M_PI/6),sin(M_PI/4),sin(M_PI/3),sin(M_PI/2)};

    ColVector x(5),y(5);

    x.initMatrix(a1);

    y.initMatrix(b1);

    Matrix nd;

    double xt=M_PI/5,yt=0;

    int flag=1;

    InterpolationPolynomial obj;

    obj.NewtonDifference_1(x,y,nd);

    cout<<nd<<endl;

    obj.NewtonDifference_2(x,y,nd);

    cout<<nd<<endl;

    obj.NewtonInterpolationValue(x,y,xt,flag,yt);

    cout<<nd<<endl;

//    obj.LagrangeInterpolationValue(x,y,xt,flag,yt);

    if(flag==1){

        double temp=sin(M_PI/5);

        cout<<"sin(pi/5),本程序结果为:"<<yt<<endl;

        cout<<x<<endl;

        cout<<"sin(pi/5),c++自带程序结果为:"<<temp<<"  errror  "<<fabs(temp-yt)<<endl;

    }else{

        cout<<"使用牛顿插值失败"<<endl;

    }

    return 0;

}

源文件:

#include "interpolationpolynomial.h"
 
InterpolationPolynomial::InterpolationPolynomial()
{
}
 
double InterpolationPolynomial::LagrangeBaseFunctionValue(ColVector &x,int k,double xt){
 
    double result=1;
    int n=x.getRowSize();
    for(int j=1;j<=n;j++){
        if(j==k){
            continue;
        }
        result=result*(xt-x[j])/(x[k]-x[j]);
    }
    return result;
}
 
//用拉格朗日插值多项式求xt处的值
void InterpolationPolynomial::LagrangeInterpolationValue(ColVector &x,ColVector &y,double xt,int &flag,double &yt){
 
    flag=1;
    int n=x.getRowSize();
    if(n!=y.getRowSize()){
        flag=0;
        return;
    }
    for(int i=1;i<=n;i++){
        double temp=x[i];
        for(int j=i+1;j<=n;j++){
            if(temp==x[j]){
                flag=0;
                return;
            }
        }
    }
    yt=0;
    for(int k=1;k<=n;k++){
        yt+=LagrangeBaseFunctionValue(x,k,xt)*y[k];
    }
}
 
//求牛顿差商表,矩阵存放结果,逐行计算
void  InterpolationPolynomial::NewtonDifference_1(ColVector &x,ColVector &y,Matrix &n_d){
 
    int n=x.getRowSize();
    n_d=Matrix(n,n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            if(j==1){
                n_d(i,j)=y[i];
            }
            else{
                n_d(i,j)=(n_d(i,j-1)-n_d(i-1,j-1))/(x[i]-x[i-(j-1)]);
            }
        }
    }
}
 
//求牛顿差商表,矩阵存放结果,逐列计算
void  InterpolationPolynomial::NewtonDifference_2(ColVector &x,ColVector &y,Matrix &n_d){
 
    int n=x.getRowSize();
    n_d=Matrix(n,n);
    //处理第一列
    for(int i=1;i<=n;i++){
        n_d(i,1)=y[i];
    }
 
    //从第二列开始
    for(int j=2;j<=n;j++){
        for(int i=j;i<=n;i++){
            n_d(i,j)=(n_d(i,j-1)-n_d(i-1,j-1))/(x[i]-x[i-(j-1)]);
        }
    }
}
 
//求牛顿差商表,向量存放结果,逐列计算(倒序计算)
void  InterpolationPolynomial::NewtonDifference_3(ColVector &x,ColVector &y){
    int n=x.getRowSize();
    //y的原始值【第一列】是0阶差商
    //cout<<y<<endl;
    //计算j阶差商
    for(int j=2;j<=n;j++){
        for(int i=n;i>=j;i--){
            y[i]=(y[i]-y[i-1])/(x[i]-x[i-(j-1)]);
        }
    }
}
 
//用牛顿插值多项式求xt处的值
void InterpolationPolynomial::NewtonInterpolationValue(
        ColVector &x,ColVector &y,double xt,int &flag,double &yt){
    flag=1;
    //点数
    int n=x.getRowSize();
    if(n!=y.getRowSize()){
        flag=0;
        return;
    }
    //横坐标互异
    for(int i=1;i<=n;i++){
        double temp=x[i];
        for(int j=i+1;j<=n;j++){
            if(temp==x[j]){
                flag=0;
                return;
            }
        }
    }
    //求差商表
    Matrix nd(n,n);
    NewtonDifference_1(x,y,nd);
 
    //计算
    /*double result=nd(1,1),temp=1;
    for(int i=2;i<=n;i++){
        temp=temp*(xt-x[i-1]);
        result=result+nd(i,i)*temp;
    }
    yt=result;*/
 
 
    //秦九韶算法
 
//    double result=nd(n,n);
//    for(int i=n-1;i>=1;i--){
//        result=result*(xt-x[i])+nd(i,i);
//    }
//    yt=result;
 
    //差商结果放到原来的向量y中
    NewtonDifference_3(x,y);
    double result=y[n];
    for(int i=n-1;i>=1;i--){
        result=result*(xt-x[i])+y[i];
    }
    yt=result;
 
    //向量y【1】存放差商表对角线元素+累加计算
    //算第j列数据
//    result = y[1];
//    for(int j=2;j<=n;j++){
//        //先计算新一轮的差商
//        for(int i=1;i<=n-(j-1);i++){
//            y[i]=(y[i+1]-y[i])/(x[i+j-1]-x[i]);
 
//        }
//        temp=temp*(xt-x[j-1]);
//        result=result+temp*y[1];
//    }
 
//    yt=result;
 
}
运行结果:

2.用表格比较Lagrange法、Newton法以及C语言自带函数对的求值结果。

Lagrange法

Newton法

C语言自带函数

0.58781

0.58781

0.58779

3.分析实验出现的问题,总结解决办法。

  1.  数据点过于稀疏,导致插值多项式的拟合效果不好。 解决办法:增加数据点的密度,使用更多的数据点进行插值计算。
  2. 构造插值多项式时,计算复杂度较高。 解决办法:使用编程软件进行计算,利用计算机的高速运算能力加快计算速度。
  3. 插值多项式的阶数过高,导致计算不稳定。 解决办法:控制插值多项式的阶数,避免过高的阶数,从而提高插值的稳定性。

实验总结:在插值多项式的求解过程中,Lagrange插值算法和Newton插值算法都是常用的方法。Newton插值算法相对于Lagrange插值算法的优点是构造插值多项式的计算过程简单,可以通过递推公式一次性得到所有的差商。在实际应用中,根据实验数据的特点和求解的需求,选择合适的插值算法进行计算,并注意处理可能出现的问题,确保插值结果的准确性和稳定性。

【实验心得】

首先,通过Lagrange插值算法,我了解到了如何通过已知数据点的横纵坐标构造出Lagrange插值多项式。这种方法相对简单直观,但需要通过计算拉格朗日基函数和差商来逐项求解。而在求解插值的时候,需要根据需要插值的点的横坐标,计算出对应的纵坐标。

然后,我学习了Newton插值算法,发现相对于Lagrange插值算法,Newton插值算法具有更好的优点。通过使用递推公式,Newton插值算法可以一次性求解出所有的差商,避免了Lagrange插值算法中需要逐项计算的过程。这样,计算的复杂度大大降低,速度也更快。

通过本次实验,我深刻理解到了插值多项式的求解过程,并且明确了Newton插值算法相对于Lagrange插值算法的优点。

得    分_____________

 

评阅日期_____________

 

教师签名_____________

相关文章:

  • AI超级智能体教程(五)---自定义advisor扩展+结构化json输出
  • FreeRtos实战从入门到精通--任务创建和删除(动态方法)--事了拂衣去,深藏功与名
  • 先知AIGC超级工场,撬动运营效率新杠杆
  • ASP.NET MVC​ 入门与提高指南八
  • (超2万字数详解)C++学习之类与对象
  • D. 例题3.2.2 整数划分问题
  • python进阶(2)二进制
  • 【分享】Winlator 10.0[特殊字符]虚拟电脑 可玩游戏办公[特殊字符]
  • mvvm 如何 实现 MultiBinding 与转换器
  • 数据结构*队列
  • python下载
  • Java从入门到精通 - Java语法
  • DeepSeek与MySQL:开启数据智能新时代
  • mysql 云服务远程linux创建数据库
  • 阿里巴巴Qwen团队发布了新一代多模态模型Qwen2.5-Omni-3B
  • Easy云盘总结篇-登录注册
  • 二种MVCC对比分析
  • MyBatis的工作原理
  • 构建高效老年基础护理实训室,培养专业护理人才
  • Servlet+tomcat
  • 探索人类的心灵这件事,永远也不会过时
  • 俄乌交换205名被俘人员,俄方人员已抵达白俄罗斯
  • 有乘客被高铁车门夹住?铁路回应:系突感不适下车,未受伤,列车正点发车
  • 美国内政部长:今年夏天美国可能发生西班牙式大停电,全怪拜登
  • 100%关税!特朗普要让美国电影100%美国制造
  • 五一假期,这些短剧值得一刷