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

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

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

该算法的基础是建立级数小于等于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

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

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

相关文章

HIVE ORC 报错ClassCastException

HIVE ORC格式的表查询报错 Failed with exception java.io.IOException:java.lang.ClassCastException: org.apache.hadoop.hive.ql.io.orc.OrcStruct cannot be cast to org.apache.hadoop.io.BinaryComparable 建表语句如下&#xff1a; CREATE EXTERNAL TABLE test_orc( te…

程序型语言VS.编译型语言

导读&#xff1a;每日[快讯精选]是由CSDN研发频道推出的特色栏目&#xff0c;每一天我们将从国外技术媒体(例如Hacker News、Reddit...等等)中挑选出有价值的新闻简讯&#xff0c;让您在第一时间掌握业界主流的技术文摘&#xff0c;每天清晨为您献上第一份技术早餐。 [1]程序型…

ancestral 箭头符号,译林版《牛津高中英语》模块五 高二上学期

《牛津英语》由译林出版社和牛津大学出版社联合编写出版。通过在南京和苏州开始的试用&#xff0c;取得了非常良好的效果&#xff0c;己在省内全面推广。有人认为新教材在教育观念和编排体系上的改革力度是八十年代以来最大的一次。它带给我们一线教师的冲击无疑是巨大的。二、…

[NOI2012]骑行川藏

题解&#xff1a; 我发现拉格朗日乘数法真是个好东西。。 我是不会说我数学竞赛求最值都是用这个东西的 由于我不太会打那个符号就用li代表通常偏导数中的lanmuda 。。。 这题里化简一下就可以得到 2 li * ki * ​(vi​−vi′​)* vi^2​1 然后一旦li确定 我们会发现这个三次函…

MAC地址和IP地址的关系

简单地说&#xff1a;ip地址是服务商给你的&#xff0c;mac地址是你的网卡物理地址。 一、IP地址 对于IP地址&#xff0c;相信大家都很熟悉&#xff0c;即指使用TCP/IP协议指定给主机的32位地址。IP地址由用点分隔开的4个8八位组构成&#xff0c;如192.168.0.1就是一个IP地址…

Linux中断 - tasklet

一、前言 对于中断处理而言&#xff0c;linux将其分成了两个部分&#xff0c;一个叫做中断handler&#xff08;top half&#xff09;&#xff0c;属于不那么紧急需要处理的事情被推迟执行&#xff0c;我们称之deferable task&#xff0c;或者叫做bottom half&#xff0c;。具体…

数字电视制播设备间的文件交换格式

在现今的数字电视演播室中&#xff0c;设备之间基本上采用信号流连接方式&#xff0c;如SDI、STDI、模拟YUV、VBS等信号流。在非线性编辑系统和播出系统与服务器之间的连接&#xff0c;还有基于MPEG-2传输流等的信号连接方式。基于信号流连接方式的主要特点是&#xff0c;传送时…

oracle 位移运算符,Oracle“(+)”运算符

在Oracle中&#xff0c;()表示JOIN中的“可选”表。 所以在你的查询中&#xff0c;select a.id, b.id, a.col_2, b.col_2, ... from a,b where a.idb.id()这是一个左外加B表与一个表。 就像现代的左连接查询一样。 (它将返回a表的所有数据&#xff0c;而不会丢失在另一边的数据…

JAVA-数据类型-复习

JAVA-数据类型-复习 Java中&#xff0c;一共有8种数据类型&#xff0c;4种整型&#xff0c;2种浮点型&#xff0c;1种用于表示Unicode编码的字符单元的字符类型char&#xff0c;1种布尔类型。 整型 类型存储需求&#xff08;字节&#xff09;一个字节包含8个位取值范围byte1-12…

什么是实体-联系图(ER图)

实体-联系图&#xff08;ER图&#xff09;数据模型中包含3种相互关联的信息&#xff1a;数据对象、数据对象的属性及数据对象彼此间相互连接的关系。 1.数据对象 数据对象是对软件必须理解的复合信息的抽象。所谓符合信息是指具有一系列不同性质或属性的事物&#xff0c;仅有单…

记录的习惯

记录的习惯 书籍是人类进步的阶梯&#xff0c;承载了人类文明进步的历程。大多数人都写过日记&#xff0c;但不知道有多少人重视过日记。常常我们会用相机记录一些生活中的场景&#xff0c;然后收藏起来&#xff0c;等到若干年后再拿出来看&#xff0c;总能感觉到很温馨很美好。…

php 去掉实体,用PHP删除除5个预定义HTML实体之外的所有实体的最佳方法-用于XHTML5输出...

我目前正在尝试提供XHTML5.目前,我在正在处理的页面上提供XHTML 1.1 Strict.那就是我为有能力的浏览器所做的.对于那些不接受XML编码数据的人,我会严格遵循HTML4.1.在尝试使用HTML5进行试验时,以HTML5格式交付时,所有功能或多或少都可以按预期工作.但是,作为XHTML5交付时,我遇到…

Flask爱家租房--发布新房源(保存房屋基本信息)

0.页面展示效果 1.后端代码 api.route("/houses/info", methods["POST"]) login_required def save_house_info():"""保存房屋的基本信息前端发送过来的json数据{"title":"","price":"","ar…

今后最有前途的媒体格式 MXF

MXF格式已经被推出几年了&#xff0c;从当初一个陌生的不为人们重视的格式逐渐获得了业内人士的认知和认可&#xff0c;现如今正被广泛应用于广播电视与后期制作领域&#xff0c;且有不断扩大之势&#xff0c;松下公司推出的基于PII卡的无磁带式标清摄像机&#xff0c;它所采用…

【c#】RabbitMQ学习文档(一)Hello World

一、简介 RabbitMQ是一个消息的代理器&#xff0c;用于接收和发送消息&#xff0c;你可以这样想&#xff0c;他就是一个邮局&#xff0c;当您把需要寄送的邮件投递到邮筒之时&#xff0c;你可以确定的是邮递员先生肯定会把邮件发送到需要接收邮件的人的手里&#xff0c;不…

什么是状态转换图

通过描绘系统的状态及引起系统状态转换的事件&#xff0c;来表示系统的行为。此外状态转换图还指明了作为特定事件的结果系统将做哪些动作&#xff08;例如&#xff0c;处理数据&#xff09;。因此状态转换图提供了行为建模机制。

Python学习笔记三

参考教程&#xff1a;廖雪峰官网https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000 一、函数的定义 Python中定义一个函数需要使用def语句&#xff0c;依次确定函数名、参数及函数体内容&#xff1a; #一个求绝对值的函数 def my_abs(x):i…

oracle中如何分页,Oracle中操作分页

mysql中分页的写法&#xff1a;select t.* from tbl_user t order by t.id limit $offset , $perpage$currentPage 1;//当前页码其中后面$sql&#xff1a;with partdata as (select rownum rowno,t.* from tablename t where column1090order by column) select * from partda…