数值计算是指在数值分析领域中的算法。数值分析是专门研究和数字以及近似值相关的数据问题,数值计算在数值分析的研究中发挥了特别重要的作用。

多项式插值是计算函数近似值的一种方法。其中函数值仅在几个点上已知。

该算法的基础是建立级数小于等于n的一个插值多项式pn(z),其中n+1是已知函数值的点的个数。

多项式插值法

许多问题都可以按照函数的方式来描述。然而,通常这个函数是未知的,我们只能通过少量的已知点来推断函数的大致模型。为了实现这个目的,在已知点之间做插值处理。如图所示,关于函数f(x),已知的点为x0...x8,在图中以黑色的圆点表示。通过插值法的帮助,我们能够获取函数在z0、z1、z2处的值,在图中以白色小方块表示。本节主要讨论多项式插值法。

多项式插值法的根本点就是要建立一个特殊形式的多项式,称为插值多项式

为了深入理解插值多项式的意义,我们先来看看多项式的一些基本法则:

首先,多项式是具有如下形式的函数:

p(x) = a0 + a1x + a2x2 + ... + anxn

这里的a0,...,an是系数当an为非零整数时,这种形式的多项式称为n阶多项式。这是多项式的指数形式,在数学问题中尤为常见。但是,在某些特定的环境中其他形式的多项式则更为简便。比如,在有关多项式插值问题中,牛顿插值多项式就是一个很好的例子

p(x) = a0 + a1 (x - c1) + a2 (x - c1)(x - c2) + ... + an(x - c1)(x - c2)...(x - cn)

这里a0,...,an是系数,而c0,...,cn是中值。注意到,当c0,...,cn全为0时,牛顿插值多项式就退化为前面定义的n阶多项式。

构建插值多项式

下面我们来看看如何对函数f(x)构建一个插值多项式。

为了对函数f(x)进行插值,要构建一个阶数小于等于n的多项式pn(z),而这又需要用到函数f(x)的n+1个已知点:x0,...,xn。这些已知点x0,...,xn就称为插值点。通过插值多项式pn(z)可以计算出函数f(x)在x=z处的近似值。插值法需要满足点z在[x0,xn]内。可以采用如下公式来构建插值多项式pn(z)。

pn(z) = f[x0] + f[x0,x1](z-x0) + f[x0,x1,x2](z-x0)(z-x1) + ... + f[x0,...,xn](z-x0)(z-x1)...(z-xn-1)

其中函数f(x)在点x0,...,xn处的值已知,而f[x0],...,f[x0,...,xn]则称为差商

差商可以通过点x0,...,xn以及函数f(x)在这些点处的值来计算得出。这就是牛顿插值多项式的计算公式。注意到该公式同牛顿插值多项式的相同点。差商的计算公式为:

f[xi,...,xj] = f(xi)                                               如果i=j

f[xi,...,xj] = ( f[xi+1,...xj] - f[xi,...xj-1] ) / (xj - xi) 如果i < j

通过这个公式不难看出,当i < j时,必须预先计算出其他的差商值。例如,要计算f[x0,x1,x2,x3],就需要先计算出f[x1,x2,x3]和f[x0,x1,x2]的值。幸运的是,可以通过一个差商表来帮助我们以一种系统的方式来计算差商值。如下图。

差商表由多行组成。最顶行保存已知点x0,...,xn 的值。第二行保存f[x0],...,f[xn]的值。要计算出表中其他的差商值,从每个待求的差商值处画一条对角线,使其回到f[xi]和f[xj](如下图中差商f[x1,x2,x3]处的虚线)要得到分母中的xi和xj,直接通过xi和xj求得。分子中的两个差商就是前一阶段计算出来的结果

当完成了整个差商表的计算后,插值多项式的系数就是从第二行开始,每行最左边的那一项

计算插值多项式

一旦确定了插值多项式的系数,对于函数f,如果我们想知道某个点处的函数值,只需要对多项式求值即可

比如,已知函数f在4个点处的函数值:x0=-3.0,f(x0)=-5.0;x1=-2.0,f(x1)=-1.1;x2=2.0,f(x2)=1.9;x3=3.0,f(x3)=4.8;现在要求出点z0=-2.5,z1=0.0,z2=1.0,z3=2.5处的函数值。由于已经知道函数f在4个点处的值,因此插值多项式为3阶。下图是3阶插值多项式p3(z)的差商表。

一旦从差商表中得到了系数,就可以采用前面介绍过的牛顿公式来构建插值多项式p3(z)

p3(z)=-5.0 + 3.9(z+3.0) + (-0.63)(z+3.0)(z+2.0) + 0.1767(z+3.0)(z+2.0)(z-2.0)

下一步可以通过该多项式计算出每个点z处的函数值。比如,在点z=-2.5处,经过如下计算得到

p3(z)=-5.0 + 3.9(-2.5+3.0) + (-0.63)(-2.5+3.0)(-2.5+2.0) + 0.1767(-2.5+3.0)(-2.5+2.0)(-2.5-2.0) = -2.694

点z1、z2、z3处的函数值可以通过相似的方法计算得出。最终结果以表格和函数图像的方式表达。如下图。

和任何其他近似算法一样,通常会有一些与插值多项式相关的误差出现,理解这一点很重要。定性的来讲,如果要使误差降至最小,构建的插值多项式必须要在函数f(x)上获取足够多的已知点才行。并且点与点之前的距离要适当,这样最终得到的多项式才能精确地表示出函数的特性。

多项式插值的接口定义

interpol


int interpol ( const double *x, const double *fx, int n, double *z, double *pz, int m );

返回值:如果插值操作成功,返回0;否则返回-1;

描述:采用多项式插值法来求得函数在某些特定点上的值。

由调用者在参数x处指定函数值已知的点集。每个已知点所对应的函数值都在fx中指定。对应待求的点由参数z来指定,而z所对应的函数值将在pz中返回x和f(x)中的元素个数由参数n来表示。z中的待求点的个数(以及pz中返回值个数)由参数m来表示。由调用者管理x、fx、z以及pz所关联的存储空间。

复杂度:O(mn2),这里m代表待求值的个数,而n代表已知点的个数。

多项式插值的实现与分析

多项式插值法主要基于对一系列期望点的插值多项式的确定。要得到这个多项式,首先必须通过计算差商来确定该多项式的系数。

首先,为差商以及待确定的系数分配存储空间。注意,由于差商表中每一行的每一项都仅依赖于其前一行的计算结果,因此,并不需要一次性保留所有的表项。所以,只为最占用空间的行分配空间即可该行将有n个条目

接下来,用fx中的值来初始化差商表的第一行。这是为计算差商表中的第三行做准备。(前两行不需要计算,因为这两行中的条目都已经保存在x和fx中)。

初始化的最后一步是在coeff[0]中保存fx[0]的值,因为这是插值多项式的第一个系数

计算差商的过程涉及一个嵌套循环,我们在循环中根据前面介绍过的公式来计算差商。在外层循环中,k用来统计正在计算的是哪一行(排除x和fx所代表的行)。在内层循环中i表示在当前行中正在计算的是哪一个条目一旦计算完一行的条目,table[0]中的值就成为插值多项式的下一个系数。因此,保存该值到coeff[k]中一旦得到插值多项式的所有系数,就可以计算出z中每个目标点的值,最后将这些值保存在pz中。

我们命名这个函数为interpol,它的时间复杂度为O(mn2这里m代表z中的元素个数(也是pz中值的个数),n代表x中(也是fx中)的元素个数。复杂度因子n2是这样得到的,变更j控制循环中的每次迭代,当前迭代中需要乘以的因子比上一轮要多一个。也就是说,当j=1时,term需要做1次乘法,当j=2时,term需要做2次乘法,持续这个过程直到j=n-1时,term需要做n-1次乘法。实际上,这就成了对1~n-1的整数求和,得到的计算时间为T(n)=(n(n+1)/2)-n,再乘以某段固定的时间。(这是由计算等差数列的著名公式得到的)。在大O记法中可以简化为O(n2)。O(mn2)中的因子m来源于针对z中的每个点计算多项式插值的过程。在第一个嵌套循环中,计算出所有的差商,其复杂度为O(n2)。因此,最终的复杂度有一个额外的因子m,该因子对实际的复杂度没有多大的影响。

示例:多项式插值的实现

/*interpol.c*/
#include <stdlib.h>
#include <string.h>#include "nummeths.h"/*interpol  */
int interpol(const double *x, const double *fx, int n, double *z, double *pz, int m)
{double term, *table, *coeff;int i,j,k;/*为差商和待确定的系数分配空间*/if((table = (double *)malloc(sizeof(double)*n)) == NULL)return -1;if((coeff = (double *)malloc(sizeof(double)*n)) == NULL){free(table);return -1;}/*初始化差商表*/memcpy(table,fx,sizeof(double)*n);/*重点:确定差商表的系数*/coeff[0] = table[0];for(k=1; k<n; k++)/*外层循环k用来统计正在计算的是哪一行*/{for(i=0; i<n-k; i++)/*内层循环i表示在当前行中正在计算的是哪一个条目(随之行数的增加,条目减少)*/{j=i+k;/*当前行的每一项中分子的差商就是其前一阶段计算的结果*/table[i] = (table[i+1] - table[i]) / (x[j] - x[i]);}/*当前行的首个条目计算结果即是多项式的下一个系数*/coeff[k]=table[0];}free(table);/*在指定点上对插值多项式进行求值(循环构造插值多项式)*/for(k=0; k<m; k++)          /*最外层:遍历z点数组*/{/*插值多项式的第一个因子*/pz[k] = coeff[0];       for(j=1; j<n; j++)      /*嵌套:构造多项式(新算式等于上一步的结果加上新因子)*/{term = coeff[j];    /*因子构成:以多项式系数为基础*/for(i=0; i<j; i++)  /*嵌套:新因子以上一步的结果乘以(z[k] - x[i])*/term=term*(z[k] - x[i]);pz[k]=pz[k] + term;}}free(coeff);return 0;
}

转载于:https://www.cnblogs.com/idreamo/p/9039000.html

数值计算算法-多项式插值算法的实现与分析相关推荐

  1. KMP算法之NEXT数组代码原理分析 - 数据结构和算法38

    KMP算法之NEXT数组代码原理分析 让编程改变世界 Change the world by program KMP算法之NEXT数组代码原理分析 NEXT数组:当模式匹配串T失配的时候,NEXT数组 ...

  2. 数据结构与算法之KMP算法中Next数组代码原理分析

    2019独角兽企业重金招聘Python工程师标准>>> 一.KMP算法之Next数组代码原理分析       1.Next数组定义 当模式匹配串T失配的时候,Next数组对应的元素指 ...

  3. 【实用算法教学】——Apriori算法,教你使用亲和性分析方法推荐电影

    本文学习如何用亲和性分析方法找出在什么情况下两个对象经常一起出现.通俗来讲,这也 叫"购物篮分析",因为曾有人用它找出哪些商品经常一起出售. 前一篇文章关注的对象为球队,并用特征描 ...

  4. 排序算法 之希尔排序及时间复杂度分析

    排序算法之 冒泡排序及性能优化(时间复杂度+空间复杂度分析) 排序算法之 简单选择排序及时间复杂度分析 排序算法之 直接插入排序及时间复杂度分析 希尔排序 算法思想:将整个待排序列分割成若干个子序列( ...

  5. GAT 算法原理介绍与源码分析

    GAT 算法原理介绍与源码分析 文章目录 GAT 算法原理介绍与源码分析 零. 前言 (与正文无关, 请忽略) 广而告之 一. 文章信息 二. 核心观点 三. 核心观点解读 四. 源码分析 4.1 G ...

  6. 电信感知测试软件,智能算法在电信业务用户体验感知分析中的应用

    摘要: 目前我国电信行业处在关键的转折期,在全业务运营后,行业竞争的核心不可避免的转移到服务质量和用户体验的层面上,各个电信运营商对服务质量的水平以及客户满意度的衡量更加重视.随着电信运营商对面向客户 ...

  7. 【老生谈算法】matlab实现电力系统暂态稳定分析——暂态稳定分析

    基于matlab的电力系统暂态稳定分析 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 说明 文档(点击下载) 本算法文档 [老生谈算法]matlab实现电力系统暂态稳定分析. ...

  8. 人工智能音乐算法的应用领域:从音频分析到音乐风格的探索

    文章目录 人工智能音乐算法的应用领域:从音频分析到音乐风格的探索 1. 引言 1.1. 背景介绍 1.2. 文章目的 1.3. 目标受众 2. 技术原理及概念 2.1. 基本概念解释 2.2. 技术原 ...

  9. 论文学习——基于优化DTW算法的水文要素时间序列数据相似性分析

    文章目录 1 摘要 2 结论 3 引言 4 水文时间序列数据相似性度量的相关研究 4.0 前人工作 4.1 提出问题 4.2 DTW动态时间弯曲距离算法 5 基于DTW的水文要素时间序列数据相似性度量 ...

最新文章

  1. 深度学习多变量时间序列预测:Bi-LSTM算法构建时间序列多变量模型预测交通流量+代码实战
  2. 单网卡部署WEB+Mail+FTP+ISA服务器之四:局域网内部署FTP和winwebmail服务器
  3. 桌面计算机怎么覆盖文件,win7系统桌面快捷方式图标被未知文件覆盖如何解决...
  4. 【自动驾驶】3. DDS 数据分发服务(Data Distribution Service)
  5. Sql Server之旅——第十三站 深入的探讨锁机制
  6. Hutool之类型转换类——Convert
  7. Linux系统(六)用户权限相关命令
  8. mangodb和php比较,php-mongodb从不同的数据库中选择
  9. Java 从入门到精通 第16章String类
  10. Linux中 vim 编辑器的使用【详细】
  11. java嵌入式软件开发工程师_嵌入式软件工程师笔试题
  12. 2018年最好用的百度网盘资源搜索神器排行
  13. maven 使用assembly 进行打包
  14. python scrapy之模拟浏览器的随机更换
  15. 智能家居语音控制系统的设计与实现
  16. 高等数学笔记:定积分换元谬误
  17. windows11专业工作站版
  18. 鸥玛软件在深交所创业板挂牌上市,系山东大学间接控股企业
  19. Git教程及常用命令
  20. 三个数据分析的技巧:找趋势、看分布、做细化

热门文章

  1. 【CodeForces - 580D】Kefa and Dishes (状压dp)
  2. bash: pcre-config: 未找到命令..._Docker 常用操作命令
  3. 国家级一级计算机考试题,国家级计算机一级考试试题
  4. 苏大微型计算机原理与应用题库,苏州大学计算机原理及应用考研复习题.pdf
  5. java 对比工具_Java几款性能分析工具的对比
  6. Android常见命令
  7. leetcode338 比特位计数
  8. 算法(6)-leetcode-explore-learn-数据结构-数组字符串的双指针技巧
  9. 学点数学(1)-随机变量函数变换
  10. CSDN写博客(字体颜色、大小)