文章介绍了拉格朗日插值多项式及其存在的龙格现象,以及如何通过切比雪夫插值优化插值误差。切比雪夫插值通过特定点间距选择,减少了在端点附近的误差扭曲。文中提供了切比雪夫多项式的定义和性质,并展示了在不同n值下,切比雪夫插值如何更接近原函数,避免龙格现象。此外,还通过实例展示了在数值逼近问题中,如何使用切比雪夫插值精确计算sin(x)函数的值。 摘要由CSDN通过智能技术生成

在文章 拉格朗日插值多项式的原理介绍及其应用 中,笔者介绍了拉格朗日插值多项式及其应用,在文章 插值多项式的龙格现象的介绍与模拟 ,我们发现插值多项式会在端点附近发生较大的扭动,即龙格现象。而切比雪夫插值是一种特定最优的点间距选取方式,其可以尽量减少插值误差。

在数值分析中,有如下定理:
( 定理1 插值误差公式 )假设P(x)是n-1或者更低阶的插值多项式,其拟合n个点 x i = cos 2 n o dd π ,其中odd表示1到2n之间的奇数,将这样的根记为 切比雪夫根 。我们将使用 切比雪夫根 作为基点的插值多项式叫作 切比雪夫插值多项式

切比雪夫多项式

定义n阶 切比雪夫多项式 T 0 ( x ) = 1 T 1 ( x ) = x T 2 ( x ) = 2 x 2 1 T 3 ( x ) = 4 x 3 3 x

根据 切比雪夫多项式 的一些基本性质,我们可以证明定理2,但这里省略,如有兴趣,可以查阅文章最后的参考文献。
在定理2中,当x的取值区间从[-1, 1]变成任意闭区间[a, b]时,我们只需对区间做伸缩变换,则有:

( 定理3 切比雪夫插值节点 )在区间[a, b], ( x x 1 ) ( x x n ) 2 n 1 ( 2 b a ) n 在区间[a, b]上恒成立。

应用1 观察切比雪夫点的插值多项式的拟合结果

我们对函数 f ( x ) = 1 + 12 x 2 1 在区间[-1, 1]上,我们选取n个切比雪夫根及其对应的函数值,对这些样本点进行多项式插值。
Python实现程序如下:

# -*- coding: utf-8 -*-
# @Time : 2023/3/8 23:40
# @Author : Jclian91
# @File : chebyshev_ploy.py
# @Place : Xuhui, Shanghai
import math
import matplotlib.pyplot as plt
# sample function
# 函数f(x)=1/(1+12*x**2)
def sample_func(x):
    return 1 / (1 + 12 * x ** 2)
# get chebyshev points from sample function with interval [-1, 1]
def get_chebyshev_points(n):
    # n: number of chebyshev points
    step = 2 / (n-1)
    x_values = [math.cos((2*i+1)*math.pi/(2*n)) for i in range(n)]
    y_values = [sample_func(x) for x in x_values]
    return x_values, y_values
# get basic lagrange polynomial unit
def get_lagrange_polynomial_unit(x_values, k, x):
    # x_values: values of x in list x_values
    # k: kth lagrange polynomial unit
    # x: variable in kth lagrange polynomial unit
    poly_unit = 1
    for i in range(len(x_values)):
        if i != k:
            poly_unit *= (x-x_values[i])/(x_values[k]-x_values[i])
    return poly_unit
# get lagrange polynomial
def get_lagrange_polynomial(x_values, y_values, x):
    poly = 0
    for i, y in enumerate(y_values):
        poly += y * get_lagrange_polynomial_unit(x_values, i, x)
    return poly
# plot curves with matplotlib
def plot_function(n):
    # plot lagrange polynomial with n sample points from sample function
    sample_x_values, sample_y_values = get_chebyshev_points(n)
    sample_points_number = 500
    x_list = [-1 + i * 2 / (sample_points_number-1) for i in range(sample_points_number)]
    original_y_list = [sample_func(x) for x in x_list]
    y_list = [get_lagrange_polynomial(sample_x_values, sample_y_values, x)for x in x_list]
    plt.plot(x_list, original_y_list, label='f(x)=1/(1+12*x**2)')
    plt.plot(x_list, y_list, label='lagrange polynomial')
    plt.title(f'Runge phenomenon with {n} chebyshev points in function f(x)=1/(1+12*x**2)')
    plt.legend()
    plt.show()
    # plt.savefig(f"{n}_basic_points.png")
if __name__ == '__main__':
    n_points = 10
    plot_function(n_points)

当n=5时,图像如下:

当n=10时,图像如下:

当n=15时,图像如下:

当n=25时,图像如下:

从中我们可以发现,当n越大,插值多项式越逼近原函数,拟合误差越小,并且我们避免了插值多项式的龙格现象,这是因为我们选取的区间点是切比雪夫点。

应用2 数值逼近

  设计程序,使得在区间 |\sin{x}-P_{n-1}(x)|=\frac{1}{n!}|(x-x_{1})\cdots(x-x_{n}))||f^{(n)}(c)|\leq \frac{(\frac{\frac{\pi}{2}-0}{2})^{n}}{n!2^{n-1}}\cdot 1 sinxPn1(x)=n!1(xx1)(xxn))∣∣f (n)(c)n!2n1(22π0)n1

经计算,当n=10时,误差界满足要求,可以精确到小数点后10位,此时切比雪夫根应为 4π+4πcos(oddπ/20).
  Python实现程序如下:

# -*- coding: utf-8 -*-
# @Time : 2023/3/9 10:37
# @Author : Jclian91
# @File : similar_to_sine_function.py
# @Place : Xuhui, Shanghai
# 利用切比雪夫多项式逼近sin(x)函数,区间为[0, pi/2]
import math
PI = math.pi    # pi in math
# sample function
# 函数f(x)=sin(x)
def sample_func(x):
    return math.sin(x)
# get chebyshev points from sample function
def get_chebyshev_points(n):
    # n: number of chebyshev points
    x_values = [PI/4 + PI/4 * math.cos((2*i+1)*PI/(2*n)) for i in range(n)]
    y_values = [sample_func(x) for x in x_values]
    return x_values, y_values
# get basic lagrange polynomial unit
def get_lagrange_polynomial_unit(x_values, k, x):
    # x_values: values of x in list x_values
    # k: kth lagrange polynomial unit
    # x: variable in kth lagrange polynomial unit
    poly_unit = 1
    for i in range(len(x_values)):
        if i != k:
            poly_unit *= (x-x_values[i])/(x_values[k]-x_values[i])
    return poly_unit
# get lagrange polynomial
def get_lagrange_polynomial(x_values, y_values, x):
    poly = 0
    for i, y in enumerate(y_values):
        poly += y * get_lagrange_polynomial_unit(x_values, i, x)
    return poly
# get similar value to sin(x) function
def get_similar_value(x):
    # x: real number in interval [0, pi/2]
    true_value = sample_func(x)
    n = 10      # chebyshev basic points number, with error < 10^-10
    x_list, y_list = get_chebyshev_points(n)
    similar_value = get_lagrange_polynomial(x_list, y_list, x)
    error = true_value - similar_value
    return f"{true_value}\t{similar_value}\t{error}"
if __name__ == '__main__':
    for x0 in [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5]:
        d = get_similar_value(x0)
        print(d)

输出结果如下:

x值sinx值逼近值误差
00.03.104458877467575e-11-3.104458877467575e-11
0.250.247403959254522940.247403959243490761.1032175173397718e-11
0.50.4794255386042030.4794255386316042-2.7401192426168564e-11
0.750.68163876002333410.6816387599931943.0140112627918825e-11
10.84147098480789650.8414709848397693-3.1872837702451307e-11
1.250.94898461935558620.94898461932066463.492162115037445e-11
1.50.99749498660405440.99749498658907021.4984236074155888e-11
  1. 数值分析(原书第2版) (美)Timothy Sauer著,裴玉茹 马赓宇译, 机械工业出版社
求解N阶比雪夫插值多项式时其过程为: (1) 利用输入函数的静态工作点I1Q和变化范围(m , n)求出N+1个比雪夫插值点; (2) 测量N+1个对应插值点的输出值; (3) 利用2(N+1)个数据,计算出比雪夫插值多项式的6个系数; (4)将系数代入比雪夫多项式,在得到输出的表达式中代入含I1的归一化公式,即可得到IB=f(I1),求I1的反函数转换自变量为t代入,即得到表达式IB=g(t)
数值计算之 插值法(4)比雪夫零点插值前言插值点选取第一类比雪夫多项式拉格朗日插值多项式的余项比雪夫零点插值后记 上篇插值法讨论了多项式插值的解,以及龙格现象。本篇将介绍一种在抽取节点时有效降低龙格现象的方法——比雪夫零点插值插值点选取 插值多项式阶数较高时,在取值空间均匀取点,容易出现龙格现象。 即区间边缘的插值结果与原函数差异很大,而区间中央的插值结果相对较好。这表明,高阶多项式插值对区间中央的节点拟合好,而对两端节点拟合效果差。 自然而然会想到,在两端多采样一些节点,在中间少采样一
Subroutine newtdd( x,y,c ) !// 计算牛顿插值系数 Implicit none Real(kind=8), intent( in ) :: x(:), y(:) Real(kind=8), intent( inout ) :: c(:...
插值,不论在数学中的数值分析中,还是在我们实际生产生活中,都不难发现它的身影,比如造船业和飞机制造业中的三次样条曲线。那么,什么是插值呢?我们可以先看一下插值的定义,如下:   (定义)如果对于每个1≤i≤n,P(xi)=yi1 \leq i \leq n,P(x_{i})=y_{i},则称函数y=P(x)y=P(x)插值数据点(x1,y1),...,(xn,yn)(x_{1},y_{1}),.
所以新手使用celery很仔细的建立文件夹名字、文件夹层级、python文件名字。 所以网上的celery博客教程虽然很多,但是并不能学会使用,因为要运行起来需要以下6个方面都掌握好,博客文字很难表达清楚或者没有写全面以下6个方面。 celery消费任务不执行或者报错NotRegistered,与很多方面有关系,如果要别人排错,至少要发以下6方面的截图,因为与一下6点关系很大。 1)整个项目目录结构, 2)@task入参 ,3)celery的配置,4)celery的配置 include ,5)cmd命令行启动参数 --queues= 的值,6)用户在启动cmd命令行时候,用户所在的文件夹。 在不规范的文件夹路径下,使用celery难度很高,一般教程都没教。 [项目文件夹目录格式不规范下的celery使用演示](https://github.com/ydf0509/celery_demo) 。 此国产分布式函数调度框架 funboost python万能通用函数加速器 https://funboost.readthedocs.io/zh-cn/latest/articles/c1.html , 从用法调用难度,用户所需代码量,超高并发性能,qps控频精确程度,支持的中间件类型,任务控制方式,稳定程度等20个方面全方位超过celery。发布性能提高1000%,消费性能提高2000%。 python万能分布式函数调度框架funboost支持python所有类型的并发模式和一切知名消息队列中间件,python函数加速器,只需要一行代码调度任意函数,框架包罗万象,万能编程功能宝典,一统编程思维,与业务不绑定,适用范围广。 pip install funboost