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

【实验性质】

综合性验

【实验目的】

掌握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插值算法的优点。

得    分_____________

 

评阅日期_____________

 

教师签名_____________

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/81626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文献总结:TPAMI端到端自动驾驶综述——End-to-End Autonomous Driving: Challenges and Frontiers

端到端自动驾驶综述 1. 文章基本信息2. 背景介绍3. 端到端自动驾驶主要使用方法3. 1 模仿学习3.2 强化学习 4. 测试基准4.1 真实世界评估4.2 在线/闭环仿真测试4.3 离线/开环测试评价 5. 端到端自动驾驶面临的挑战5.1 多模态输入5.2 对视觉表征的依赖5.3 基于模型的强化学习的世…

PostgreSQL:pgAdmin 4 使用教程

pgAdmin 4 是一个用于管理和维护 PostgreSQL 数据库的强大工具。它提供了一个图形化界面&#xff0c;使用户能够轻松地连接到数据库、创建表、运行 SQL 语句以及执行其他数据库管理任务。 安装和使用 安装 pgAdmin 4 安装 pgAdmin 4 非常简单。下载并运行安装程序&#xff0…

Java学习手册:关系型数据库基础

一、关系型数据库概述 关系型数据库是一种基于关系模型的数据库&#xff0c;它将数据组织成一个或多个表&#xff08;或称为关系&#xff09;&#xff0c;每个表由行和列组成。每一列都有一个唯一的名字&#xff0c;称为属性&#xff0c;表中的每一行是一个元组&#xff0c;代…

wpf CommandParameter 传递MouseWheelEventArgs参数

在 WPF 中通过 CommandParameter 传递 MouseWheelEventArgs 参数时&#xff0c;需结合 ‌事件到命令的转换机制‌ 和 ‌参数转换器‌ 来实现。以下是具体实现方案及注意事项&#xff1a; 一、核心实现方法 1. ‌使用 EventToCommand 传递原始事件参数‌ 通过 Interaction.Tr…

八大排序之选择排序

本篇文章将带你详细了解八大基本排序中的选择排序 目录 &#xff08;一&#xff09;选择排序的时间复杂度和空间复杂度及稳定性分析 &#xff08;二&#xff09;代码实现 (三)输出结果 选择排序的基本原理是&#xff1a;每次从待排序的数组中找出最大值和最小值。具体流程是…

【算法学习】哈希表篇:哈希表的使用场景和使用方法

算法学习&#xff1a; https://blog.csdn.net/2301_80220607/category_12922080.html?spm1001.2014.3001.5482 前言&#xff1a; 在之前学习数据结构时我们就学习了哈希表的使用方法&#xff0c;这里我们主要是针对哈希表的做题方法进行讲解&#xff0c;都是leetcode上的经典…

Java 中如何实现自定义类加载器,应用场景是什么?

在 Java 中&#xff0c;可以通过继承 java.lang.ClassLoader 类来实现自定义类加载器。自定义类加载器可以控制类的加载方式&#xff0c;实现一些特殊的应用场景。 实现自定义类加载器的步骤&#xff1a; 继承 java.lang.ClassLoader 类。 重写 findClass(String name) 方法 …

信创开发中跨平台开发框架的选择与实践指南

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

WebRTC 服务器之Janus架构分析

1. Webrtc三种类型通信架构 1.1 1 对 1 通信 1 对 1 通信模型设计的主要⽬标是尽量让两个终端进⾏直联&#xff0c;这样即可以节省服务器的资源&#xff0c;⼜可以提⾼ ⾳视频的服务质量。WebRTC ⾸先尝试两个终端之间是否可以通过 P2P 直接进⾏通信&#xff0c;如果⽆法直接…

数字化转型进阶:26页华为数字化转型实践分享【附全文阅读】

本文分享了华为数字化转型的实践经验和体会。华为通过数字化变革,致力于在客户服务、供应链、产品管理等方面提高效率,并把数字世界带入每个组织,构建万物互联的智能世界。华为的数字化转型愿景是成为行业标杆,通过推进数字化战略、构建面向业务数字化转型的IT组织阵型、坚…

Hal库下备份寄存器

首先要确保有外部电源给VBAT供电 生成后应该会有这两个文件&#xff08;不知道为什么生成了好几次都没有&#xff0c;复制工程在试一次就有了&#xff09; 可以看到stm32f407有20个备份寄存器 读写函数 void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t Backup…

使用 Vue3 + Webpack 和 Vue3 + Vite 实现微前端架构(基于 Qiankun)

在现代前端开发中&#xff0c;微前端架构逐渐成为一种流行的解决方案&#xff0c;尤其是在大型项目中。通过微前端&#xff0c;我们可以将一个复杂的单体应用拆分为多个独立的小型应用&#xff0c;每个子应用可以独立开发、部署和运行&#xff0c;同时共享主应用的基础设施。本…

【c++】【STL】list详解

目录 list的作用list的接口构造函数赋值运算符重载迭代器相关sizeemptyfrontbackassignpush_frontpop_frontpush_backpop_backinserteraseswapresizeclearspliceremoveremove_ifuniquemergesortreverse关系运算符重载&#xff08;非成员函数&#xff09; list的模拟实现结点类迭…

Redis持久化:

什么是Redis持久化&#xff1a; Redis 持久化是指将 Redis 内存中的数据保存到硬盘等持久化存储介质中&#xff0c;以便在 Redis 服务器重启或出现故障时能够恢复数据&#xff0c;保证数据的可靠性和持续性。Redis 提供了两种主要的持久化方式&#xff1a;RDB&#xff08;Redi…

VBA 64位API声明语句第009讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…

在pycharm profession 2020.3将.py程序使用pyinstaller打包成exe

一、安装pyinstaller 在pycharm的项目的Terminal中运行pip3 install pyinstaller即可。 安装后在Terminal中输入pip3 list看一下是否成功 二、务必在在项目的Terminal中输入命令打包&#xff0c;命令如下&#xff1a; python3 -m PyInstaller --noconsole --onefile xxx.py …

Unity SpriteRenderer(精灵渲染器)

&#x1f3c6; 个人愚见&#xff0c;没事写写笔记 &#x1f3c6;《博客内容》&#xff1a;Unity3D开发内容 &#x1f3c6;&#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f50e;SpriteRenderer:精灵渲染器 &#x1f4a1;Sprite Renderer是精灵渲染器&#xff0c;所有…

2.LED灯的控制和按键检测

目录 STM32F103的GPIO口 GPIO口的作用 GPIO口的工作模式 input输入检测 -- 向内检测 output控制输出 -- 向外输出 寄存器 寄存器地址的确定 配置GPIO口的工作模式 时钟的开启和关闭 软件编程驱动 LED 灯 硬件 软件 软件编程驱动 KEY 按键 硬件 软件 按键消抖 代码 STM32F…

Flink 的状态机制

在实时流处理领域&#xff0c;状态管理是构建复杂业务逻辑的核心能力。Apache Flink 通过统一的状态抽象和高效的容错机制&#xff0c;为开发者提供了从毫秒级窗口聚合到 TB 级历史数据关联的全场景支持。本文将深入剖析 Flink 状态机制的底层原理&#xff0c;结合实际案例展示…

【查看.ipynp 文件】

目录 如何打开 .ipynb 文件&#xff1f; 如果确实是 .ipynp 文件&#xff1a; .ipynp 并不是常见的 Jupyter Notebook 文件格式。通常&#xff0c;Jupyter Notebook 文件的扩展名是 .ipynb&#xff08;即 Interactive Python Notebook&#xff09;。如果你遇到的是 .ipynb 文…