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

R语言实现牛顿插值

文章目录

    • 4 差商与牛顿插值
      • 差商
      • 牛顿插值

4 差商与牛顿插值

差商

如果采取间隔不等的采样,差商会变得稍显复杂,对于 x 0 , x 1 , … , x n x_0,x_1,\ldots,x_n x0,x1,,xn,若与 y 0 , y 1 , … , y n y_0,y_1,\ldots,y_n y0,y1,,yn通过映射 f f f一一对应,则定义比值

f [ x 0 , x 1 ] = f ( x 1 ) − f ( x 0 ) x 1 − x 0 f[x_0,x_1]=\frac{f(x_1)-f(x_0)}{x_1-x_0} f[x0,x1]=x1x0f(x1)f(x0)

f ( x ) f(x) f(x)关于节点 x 0 , x 1 x_0,x_1 x0,x1的一阶差商。

由于在计算二阶差商的时候,不可避免地涉及到3个点,所以二阶差商定义为

f [ x 0 , x 1 , x 2 ] = f [ x 0 , x 2 ] − f [ x 0 , x 1 ] x 2 − x 1 f[x_0,x_1,x_2]=\frac{f[x_0,x_2]-f[x_0,x_1]}{x_2-x_1} f[x0,x1,x2]=x2x1f[x0,x2]f[x0,x1]

k k k阶差商定义为

f [ x 0 , x 1 , … , x k ] = f [ x 0 , x 1 , … , x k − 2 , x k ] − f [ x 0 , x 1 , … , x k − 1 ] x k − x k − 1 f[x_0,x_1,\ldots,x_k]=\frac{f[x_0,x_1,\ldots,x_{k-2},x_k]-f[x_0,x_1,\ldots,x_{k-1}]}{x_k-x_{k-1}} f[x0,x1,,xk]=xkxk1f[x0,x1,,xk2,xk]f[x0,x1,,xk1]

若将 k k k阶差商展开,则可表示为函数值 f ( x 0 ) , f ( x 1 ) , … , f ( x k ) f(x_0),f(x_1),\ldots,f(x_k) f(x0),f(x1),,f(xk)的线性组合,且每一项的分母必可写为 k k k x i − x j x_i-x_j xixj的乘积,可以表示为

f [ x 0 , x 1 , … , x k ] = ∑ j = 0 k f ( x j ) ( x j − x 0 ) … ( x j − x j − 1 ) ( x j − x j + 1 ) … ( x j − x k ) f[x_0,x_1,\ldots,x_k]=\displaystyle\sum_{j=0}^k\frac{f(x_j)}{(x_j-x_0)\ldots(x_j-x_{j-1})(x_j-x_{j+1})\ldots(x_j-x_k)} f[x0,x1,,xk]=j=0k(xjx0)(xjxj1)(xjxj+1)(xjxk)f(xj)

其中第 j j j项的分母中不存在 x j − x j x_j-x_j xjxj。则

f [ x 0 , … , x k − 1 ] = ∑ j = 0 k − 1 f ( x j ) ( x j − x 0 ) … ( x j − x j − 1 ) ( x j − x j + 1 ) … ( x j − x k − 1 ) f [ x 1 , … , x k ] = ∑ j = 1 k f ( x j ) ( x j − x 1 ) … ( x j − x j − 1 ) ( x j − x j + 1 ) … ( x j − x k ) \begin{aligned} f[x_0,\ldots,x_{k-1}]&=\displaystyle\sum_{j=0}^{k-1}\frac{f(x_j)}{(x_j-x_0)\ldots(x_j-x_{j-1})(x_j-x_{j+1})\ldots(x_j-x_{k-1})}\\ f[x_1,\ldots,x_k]&=\displaystyle\sum_{j=1}^{k}\frac{f(x_j)}{(x_j-x_1)\ldots(x_j-x_{j-1})(x_j-x_{j+1})\ldots(x_j-x_{k})} \end{aligned} f[x0,,xk1]f[x1,,xk]=j=0k1(xjx0)(xjxj1)(xjxj+1)(xjxk1)f(xj)=j=1k(xjx1)(xjxj1)(xjxj+1)(xjxk)f(xj)

易得

f [ x 0 , x 1 , … , x k ] = f [ x 1 , x 2 , … , x k ] − f [ x 0 , x 1 , … , x k − 1 ] x k − x 0 f[x_0,x_1,\ldots,x_k]=\frac{f[x_1,x_2,\ldots,x_k]-f[x_0,x_1,\ldots,x_{k-1}]}{x_k-x_0} f[x0,x1,,xk]=xkx0f[x1,x2,,xk]f[x0,x1,,xk1]

根据这个表达式,可以通过一个简单的递归程序计算数组的差商

# 差商算法,x,y为同等长度的数组
diffDiv<-function(x,y){
    end = length(x)
    ind = 2:end #索引
    return(
        if(end==1) y[1]
        else (diffDiv(x[ind],y[ind])
            -diffDiv(x[ind-1],y[ind-1]))/(x[end]-x[1])
    )
}

如果要计算阶数为k的差商,只需重复调用diffDiv

kDiffDiv <- function(x,y,k){
    len <- length(x)
    if(len<k) return(0)
    d<-rep(0,len-k)
    for(i in 1:(len-k))
        d[i] <- diffDiv(x[i:(i+k)],y[i:(i+k)])
    return(d)
}

据此,绘制出 y = x 5 y=x^5 y=x5这个函数的差商,

> plot(x,y)
> k = 1
> lines(x[1:(end-k)],kDiffDiv(x,y,k),col="red")
> k = 2
> lines(x[1:(end-k)],kDiffDiv(x,y,k),col="green")
> k = 3
> lines(x[1:(end-k)],kDiffDiv(x,y,k),col="blue")
> k = 4
> lines(x[1:(end-k)],kDiffDiv(x,y,k),col="purple")
> k = 5
> lines(x[1:(end-k)],kDiffDiv(x,y,k),col="yellow")
> k = 6
> lines(x[1:(end-k)],kDiffDiv(x,y,k),col="gray")

如图所示

在这里插入图片描述

牛顿插值

可见差商与微分在阶数上有着一致的趋势。那么,知道了差商之后,可以做点什么呢?

根据差商定义,可得

f ( x ) = f ( x 0 ) + f [ x , x 0 ] ( x − x 0 ) f [ x , x 0 ] = f [ x 0 , x 1 ] + f [ x , x 0 , x 1 ] ( x − x 1 ) ⋮ f [ x , x 0 , … , x n − 1 ] = f [ x 0 , x 1 , … , x n ] + f [ x , x 0 , x 1 , … , x n ] ( x − x n ) \begin{aligned} f(x) &= f(x_0) + f[x,x_0](x-x_0)\\ f[x,x_0] &= f[x_0,x_1] + f[x,x_0,x_1](x-x_1)\\ &\vdots\\ f[x,x_0,\ldots,x_{n-1}] &= f[x_0,x_1,\ldots,x_n] + f[x,x_0,x_1,\ldots,x_n](x-x_n) \end{aligned} f(x)f[x,x0]f[x,x0,,xn1]=f(x0)+f[x,x0](xx0)=f[x0,x1]+f[x,x0,x1](xx1)=f[x0,x1,,xn]+f[x,x0,x1,,xn](xxn)

可见,通过差商可以逼近函数的真实值,将上式合并可得

f ( 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 n ] ( x − x 0 ) ( x − x 1 ) … ( x − x n − 1 ) + f [ x 0 , x 1 , … , x n ] ω n + 1 ( x ) = N n ( x ) + R n ( x ) \begin{aligned} f(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)\\ &+\ldots+f[x_0,x_1,\ldots,x_n](x-x_0)(x-x_1)\ldots(x-x_{n-1})\\ &+f[x_0,x_1,\ldots,x_n]\omega_{n+1}(x)\\ =&N_n(x)+R_n(x) \end{aligned} f(x)==f(x0)+f[x0,x1](xx0)+f[x0,x1,x2](xx0)(xx1)++f[x0,x1,,xn](xx0)(xx1)(xxn1)+f[x0,x1,,xn]ωn+1(x)Nn(x)+Rn(x)

其中,

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 n ] ( x − x 0 ) ( x − x 1 ) … ( x − x n − 1 ) R n ( x ) = f [ x 0 , x 1 , … , x n ] ω n + 1 ( x ) \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)+\\ &\ldots+f[x_0,x_1,\ldots,x_n](x-x_0)(x-x_1)\ldots(x-x_{n-1})\\ R_n(x)=&f[x_0,x_1,\ldots,x_n]\omega_{n+1}(x) \end{aligned} Nn(x)=Rn(x)=f(x0)+f[x0,x1](xx0)+f[x0,x1,x2](xx0)(xx1)++f[x0,x1,,xn](xx0)(xx1)(xxn1)f[x0,x1,,xn]ωn+1(x)

其中, ω n + 1 ( x ) = ( x − x 0 ) ( x − x 1 ) … ( x − x n ) \omega_{n+1}(x)=(x-x_0)(x-x_1)\ldots(x-x_n) ωn+1(x)=(xx0)(xx1)(xxn) N n ( x ) N_n(x) Nn(x)就是大名鼎鼎的牛顿插值公式,其是一种十分强大的插值算法,递推式可以写为

N n + 1 ( x ) = N n ( x ) + f [ x 0 , x 1 , … , x n + 1 ] ω n + 1 ( x ) N_{n+1}(x) = N_{n}(x) + f[x_0,x_1,\ldots,x_{n+1}]\omega_{n+1}(x) Nn+1(x)=Nn(x)+f[x0,x1,,xn+1]ωn+1(x)

由于牛顿插值的本质是多项式插值,所以关键是得到插值多项式的系数。记 N n , i N_{n,i} Nn,i n n n阶牛顿多项式的第 i i i项,记 ω n , i \omega_{n,i} ωn,i n n n ω \omega ω多项式的第 i i i项,则其递推式可以写为

N n ( x ) = ∑ i = 0 n N n , i x i = ∑ i = 0 n − 1 N n − 1 , i x i + f [ x 0 , x 1 , … , x n ] ∑ i = 0 n ω n , i x i N_n(x)=\sum_{i=0}^{n}N_{n,i}x^i=\sum_{i=0}^{n-1}N_{n-1,i}x^i + f[x_0,x_1,\ldots,x_n]\sum_{i=0}^{n}\omega_{n,i}x^i Nn(x)=i=0nNn,ixi=i=0n1Nn1,ixi+f[x0,x1,,xn]i=0nωn,ixi

∑ i = 0 n N n , i x i = ∑ i = 0 n − 1 ( N n − 1 , i + f [ x 0 , x 1 , … , x n ] ω n , i ) x i + f [ x 0 , x 1 , … , x n ] ω n , n x n \sum_{i=0}^{n}N_{n,i}x^i=\sum_{i=0}^{n-1}(N_{n-1,i} + f[x_0,x_1,\ldots,x_n]\omega_{n,i})x^i+f[x_0,x_1,\ldots,x_n]\omega_{n,n}x^n i=0nNn,ixi=i=0n1(Nn1,i+f[x0,x1,,xn]ωn,i)xi+f[x0,x1,,xn]ωn,nxn

拆分之后得到

N n , i = { N n − 1 , i + f [ x 0 , x 1 , … , x n ] ω n , i , i < n f [ x 0 , x 1 , … , x n ] ω n , n , i = n N_{n,i}=\left\{ \begin{aligned} &N_{n-1,i} + f[x_0,x_1,\ldots,x_n]\omega_{n,i},& i<n\\ &f[x_0,x_1,\ldots,x_n]\omega_{n,n},\quad &i=n \end{aligned}\right. Nn,i={Nn1,i+f[x0,x1,,xn]ωn,i,f[x0,x1,,xn]ωn,n,i<ni=n

由于 ω n ( x ) = ( x − x 0 ) ( x − x 1 ) … ( x − x n − 1 ) = ω n − 1 ( x ) ∗ ( x − x n ) \omega_{n}(x)=(x-x_0)(x-x_1)\ldots(x-x_{n-1})=\omega_{n-1}(x)*(x-x_n) ωn(x)=(xx0)(xx1)(xxn1)=ωn1(x)(xxn),则

ω n , i = { ω n − 1 , 0 ∗ ( − x n ) i = 0 ω n − 1 , i ∗ ( − x n ) + ω n − 1 , i − 1 i ∈ [ 1 , n ] 1 i = n + 1 \omega_{n,i}=\left\{\begin{aligned} &\omega_{n-1,0}*(-x_{_n})&i=0\\ &\omega_{n-1,i}*(-x_{_n})+\omega_{n-1,i-1} & i\in[1,n]\\ &1&i=n+1 \end{aligned}\right. ωn,i= ωn1,0(xn)ωn1,i(xn)+ωn1,i11i=0i[1,n]i=n+1

polyMulti<-function(x){
    n = length(x)
    if(n<2) return(c(-x,1))
    omega = rep(0,n+1)
    omega[1] = - x[1]
    omega[2] = 1
    for(i in 2:n){
        omega[2:i] = -x[i]*omega[2:i]*+omega[1:(i-1)]
        omega[1] = -x[i]*omega[1]
        omega[i+1] = 1
    }
    return(omega)
}

Newton<-function(x,y){
    n = length(x)
    N = rep(0,n+1)
    N[1]=y[1]
    for(i in 1:n){
        omega = polyMulti(x[1:i])
        d = kDiffDiv(x[1:i],y[1:i],i-1)
        N[1:i] = N[1:i] + d*omega[1:i]
        N[i+1] = d*omega[i+1]
    }
    return(N)
}

验证一下

x = sort(rnorm(10))
y = x^5+2*x^4
N = Newton(x,y)
Y = y*0
for(i in 1:length(Y))
    for(j in 1:length(N))
        Y[i] = Y[i]+N[j]*x[i]^(j-1)
plot(x,y)
lines(x,Y)

在这里插入图片描述

可见效果还是不错的。

相关文章:

  • jenkins结合gitlable企业集成部署实战
  • 前端面试题——React重点
  • 超级详细的PMP复习方法,3A拿下考试不发愁!
  • C语言进阶——通讯录
  • C#语言实例源码系列-实现停车场系统项目-下
  • 我辛辛苦苦做了一个月的项目,组长年底用来写了晋升PPT
  • 【云原生进阶之容器】第四章Operator原理4.2节--CRD
  • 牛客竞赛每日俩题 - Day14
  • Three.js一学就会系列:05 加载3D模型
  • Python2.x和3.x主要差异总结
  • Vue中引入react组件
  • python的8大核心语句,你确定不来看看嘛,那格局就小啦
  • windows排查问题常用命令
  • 2023年网络安全比赛--跨站脚本攻击中职组(超详细)
  • SkyEye:针对飞行模拟器的仿真解决方案
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • django开发-定时任务的使用
  • Flannel解读
  • interface和setter,getter
  • MySQL几个简单SQL的优化
  • Redis 中的布隆过滤器
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • vue-cli在webpack的配置文件探究
  • vue-router的history模式发布配置
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 解析 Webpack中import、require、按需加载的执行过程
  • 经典排序算法及其 Java 实现
  • 面试总结JavaScript篇
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 听说你叫Java(二)–Servlet请求
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 我有几个粽子,和一个故事
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 我们雇佣了一只大猴子...
  • ${ }的特别功能
  • (4)logging(日志模块)
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (转)Linq学习笔记
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .bat批处理(一):@echo off
  • .libPaths()设置包加载目录
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET CORE 第一节 创建基本的 asp.net core
  • .NET Core 2.1路线图
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .net 按比例显示图片的缩略图
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .net6使用Sejil可视化日志
  • .NET导入Excel数据