导数,差商,牛顿插值法

22 篇文章 1 订阅
18 篇文章 0 订阅

1 差商的定义

设有函数f (x)以及自变量的一系列互不相等的x_{0},x_{1}...x_{n}的值 f(xi),称

f[x_{i},x_{j}]=\frac{f(x_{i})-f(x_{j})}{x_{i}-x_{j}}(i\neq j , x_{i} \neq x_{j} )

f (x)在点x_{i},x_{j}处的一阶差商,并记作f[x_{i},x_{j}]。又称

f[x_{i},x_{j},x_{k}]=\frac{f[x_{i},x_{j}]-f[x_{j},x_{k}]}{x_{i}-x_{k}}(i\neq j \neq k , x_{i} \neq x_{j} \neq x_{k} )

f (x)在点x_{i},x_{j},x_{k}处的二阶差商;称:

f[x_{0},x_{1},x_{2} ... x_{n}]=\frac{f[x_{0},x_{1} ... x_{n}]-f[x_{1},x_{2}...x_{n-1}]}{x_{0}-x_{n} }( x_{0} \neq x_{1} \neq ... x_{n} )

f (x)在点x_{0},x_{1}...x_{n}处的n阶差商。

 

2 牛顿插值法的推导

有了差商的定义,就很容易推出牛顿插值的公式。

根据均差定义 , 把 x 看成[ a, b] 上一点 , 可得
f(x) = f(x_{0}) + f[x_{0},x](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_{1},x_{2}...x_{n-1}] = f[x,x_{0},x_{1},x_{2}...x_{n}] + f[x,x_{1},x_{2} ... x_{n}](x-x_{n})

把后一式代入前一式,得到:

f(x) = f(x_{0}) +f[x,x_{0}](x-x_{0})+f[x,x_{0},x_{1}](x-x_{1}) ... + f[x,x_{0},x_{1}...x_{n-1}](x-x_{0})(x-x_{1})(x-x_{2})...(x-x_{n-1})+f[x,x_{0},x_{1}...x_{n}](x-x_{0})(x-x_{1})(x-x_{2})...(x-x_{n})

3 牛顿插值法的代码实现

由牛顿插值法的公式知道,要实现牛顿插值,关键是要实现各阶差商的计算;而要计算差商,首先需要计算一阶差商,然后用一阶差商计算二阶差商,用二阶差商计算三阶差商...

"""
@brief: 获得牛顿插值函数(非递归实现)
@
"""
def get_Newton_inter_Ex(xi=[], fi=[]):
    def Newton_inter(x):
        ai = fi.copy()
        #计算k阶系数,即计算k阶差商,从第一阶开始计算
        for k in range(1, len(xi)-1):
            for j in range(len(xi)-1,k-1,-1):
                ai[j] = (ai[j]-ai[j-1]) /(xi[j]-xi[j-k])
        result = ai[0]
        h = 1.0
        for j in range(1,len(xi)-1):
            h *= (x-xi[j-1])
            result += ai[j] * h
        return result

    return Newton_inter

然后看下完整的代码,通过牛顿插值拟合函数:

# -*- coding: utf-8 -*-
"""
Created on Thu Nov 17 18:34:21 2016

@author: idwtwt
@brief: 牛顿插值法
"""
import numpy as np
import matplotlib.pyplot as plt



"""
@brief: 获得牛顿插值函数(非递归实现)
@
"""
def get_Newton_inter_Ex(xi=[], fi=[]):
    def Newton_inter(x):
        ai = fi.copy()
        #计算k阶系数,即计算k阶差商
        for k in range(1, len(xi)-1):
            for j in range(len(xi)-1,k-1,-1):
                ai[j] = (ai[j]-ai[j-1]) /(xi[j]-xi[j-k])
        result = ai[0]
        h = 1.0
        for j in range(1,len(xi)-1):
            h *= (x-xi[j-1])
            result += ai[j] * h
        return result

    return Newton_inter


"""
demo:
"""
if __name__ == '__main__':
    ''' 插值节点, 这里用二次函数生成插值节点,每两个节点x轴距离位10 '''
    sr_x = np.linspace(-50, 50, 12)
    sr_fx = [1/(1+i**2) for i in sr_x]

    Nx = get_Newton_inter_Ex(sr_x, sr_fx)  # 获得插值函数

    tmp_x = [i for i in range(-50, 51)]  # 测试用例
    tmp_y = [Nx(i) for i in tmp_x]  # 根据插值函数获得测试用例的纵坐标

    ''' 画图 '''
    plt.figure("Newton")
    ax1 = plt.subplot(111)
    plt.sca(ax1)
    plt.plot(sr_x, sr_fx, linestyle='', marker='o', color='b')
    plt.plot(tmp_x, tmp_y, linestyle='--', color='r')
    plt.show()

看下拟合效果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值