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

数值分析——分段低次插值

关键字:Matalb;曲线拟合;高次病态特性;分段低次插值

系列文章目录

数值分析——拉格朗日插值
数值分析——牛顿插值多项式
数值分析——埃尔米特(Hermit)插值


文章目录

  • 系列文章目录
  • 前言
  • 一、理论推导
    • 1.高次插值的病态特性
    • 2.分段线性插值
    • 3.分段三次Hermit插值
  • 二、MATLAB
    • 1.分段线性插值
    • 2.分段Hermit插值
    • 3.测试程序
  • 总结
  • 参考文献


前言

  一般认为对于区间 [ a , b ] \left[a,b\right] [a,b]上给出的节点做插值多项式 L n ( x ) L_n\left( x \right) Ln(x)近似 f ( x ) f\left( x \right) f(x),一般总认为 L n ( x ) L_n\left( x \right) Ln(x)的次数 n n n越高,插值函数逼近原函数的效果越好,但实际上并非如此。这是因为对于任意的插值节点,当 n → ∞ n\rightarrow \infty n时, L n ( x ) L_n\left( x \right) Ln(x)不一定收敛于 f ( x ) f\left( x \right) f(x)。为了解决高次插值的问题,学者们提出了分段低次插值的方法,即将被拟合函数 f ( x ) f\left( x \right) f(x)分为多个小区间,在小区间上利用低次多项式进行插值拟合。

本文对一些复杂的流程与概念进行了简化与省略,如果想详细了解的小伙伴可以参考李庆扬老师的《数值分析 -第5版》的第2章(需要电子版请私戳)


一、理论推导

1.高次插值的病态特性

  高次插值的病态特性指的是,在对某些函数 f ( x ) f\left( x \right) f(x)进行拟合时,高次多项式的插值函数拟合效果反而不好的特性。例如针对函数:
f ( x ) = 1 x 2 + 1 (1) f\left( x \right)=\frac{1}{x^2+1} \tag{1} f(x)=x2+11(1)使用拉格朗日插值法,在插值节点 x = − 5 , − 4 , − 3 , − 2 , − 1 , 0 , 1 , 2 , 3 , 4 , 5 x=-5,-4,-3,-2,-1,0,1,2,3,4,5 x=5,4,3,2,1,0,1,2,3,4,5拟合十次插值函数:

% 高次插值的动态特性
x=-5:0.05:5;
y=zeros(1,length(x));                                                       % 原函数y值
xInArr=-5:1:5;                                                              % 插值节点x值
yInArr=zeros(1,length(xInArr));                                             % 插值节点y值
yOutArr=zeros(1,length(x));                                                 % 插值函数y值
% 计算插值函数y值
for i=1:1:length(xInArr)yInArr(i)=1/(xInArr(i)^2+1);
end
% 计算十次插值多项式的poly数组
L10=func_LagrangeInterpolation(xInArr,yInArr,11);
% 计算原函数与插值函数y值
for i=1:1:length(x)y(i)=1/(x(i)^2+1);yOutArr(i)=polyval(L10,x(i));
end
% 画图
plot(x,y,'k-',x,yOutArr,'r:','LineWidth',2);
xlabel('x');
ylabel('y');
legend('f(x)','L10(x)');

其中func_LagrangeInterpolation是拉格朗日插值法函数,具体内容可参考数值分析——拉格朗日插值中的代码。得到的对比结果:
Alt

图1.1 高次插值函数的病态特性

其中红色的点线为十次拉格朗日插值函数 L 10 ( x ) L_{10}\left( x \right) L10(x),黑色的曲线为原函数 f ( x ) f\left( x \right) f(x),可以看到插值函数的拟合效果并不是很好。

2.分段线性插值

  分段线性插值就是通过插值点用折现段连接起来逼近 f ( x ) f\left( x \right) f(x)。若在已知节点 a = x 0 < x 1 < ⋯ < x n = b a=x_0<x_1<\cdots<x_n=b a=x0<x1<<xn=b,已知各点的函数值f_0,f_1,f_2,\cdots,f_{n-1},f_n,则可以设计一个插值函数:
I h ( x ) = x − x k + 1 x k − x k + 1 f k + x − x k x k + 1 − x k f k + 1 , x k ≤ x ≤ x k + 1 , k = 0 , 1 , ⋯ , n − 1 (2) I_h\left( x \right)= \frac{x-x_{k+1}}{x_{k}-x_{k+1}}f_k+ \frac{x-x_{k}}{x_{k+1}-x_{k}}f_{k+1}, \ \ x_k \le x \le x_{k+1}, \ \ k=0,1,\cdots,n-1 \tag{2} Ih(x)=xkxk+1xxk+1fk+xk+1xkxxkfk+1,  xkxxk+1,  k=0,1,,n1(2)该插值函数满足:

  1. 函数属于在区间 [ a , b ] [a,b] [a,b]连续的函数空间: I h ( x ) ∈ C [ a , b ] I_h\left( x \right)\in C\left[a,b\right] Ih(x)C[a,b]
  2. 插值函数在所有插值点的数值都等于原函数: I h ( x ) = f k ( k = 0 , 1 , ⋯ , n − 1 ) I_h\left( x \right)=f_k\left(k=0,1,\cdots,n-1\right) Ih(x)=fk(k=0,1,,n1)
  3. 插值函数在每个小区间上是线性函数: I h ( x ) = k x + b I_h\left( x \right)=kx+b Ih(x)=kx+b

3.分段三次Hermit插值

  分段线性插值函数的导数是间断的,如果在插值节点 a = x 0 < x 1 < ⋯ < x n = b a=x_0<x_1<\cdots<x_n=b a=x0<x1<<xn=b上,不仅已知函数值 f 0 , f 1 , f 2 , ⋯ , f n − 1 , f n f_0,f_1,f_2,\cdots,f_{n-1},f_n f0,f1,f2,,fn1,fn,而且已知函数导数值 f 0 ′ , f 1 ′ , f 2 ′ , ⋯ , f n − 1 ′ , f n ′ f^{'}_0,f^{'}_1,f^{'}_2,\cdots,f^{'}_{n-1},f^{'}_n f0,f1,f2,,fn1,fn,则可以设计一个插值函数:
I h ( x ) = ( x − x k + 1 x k − x k + 1 ) 2 ( 1 + 2 x − x k x k + 1 − x k ) f k + ( x − x k x k + 1 − x k ) 2 ( 1 + 2 x − x k + 1 x k − x k + 1 ) f k + 1 + ( x − x k + 1 x k − x k + 1 ) 2 ( x − x k ) f k ′ + ( x − x k x k + 1 − x k ) 2 ( x − x k + 1 ) f k + 1 ′ , x k ≤ x ≤ x k + 1 , k = 0 , 1 , ⋯ , n − 1 (3) \begin{align} I_h\left( x \right)= &\left(\frac{x-x_{k+1}}{x_{k}-x_{k+1}}\right)^2 \left( 1+2\frac{x-x_k}{x_{k+1}-x_{k}} \right)f_k+ \left(\frac{x-x_{k}}{x_{k+1}-x_{k}}\right)^2\left( 1+2\frac{x-x_{k+1}}{x_{k}-x_{k+1}} \right)f_{k+1} \\ &+\left(\frac{x-x_{k+1}}{x_{k}-x_{k+1}}\right)^2\left( x-x_k \right)f^{'}_k+\left(\frac{x-x_{k}}{x_{k+1}-x_{k}}\right)^2\left( x-x_{k+1} \right)f^{'}_{k+1}, \ \ x_k \le x \le x_{k+1}, \ \ k=0,1,\cdots,n-1 \end{align} \tag{3} Ih(x)=(xkxk+1xxk+1)2(1+2xk+1xkxxk)fk+(xk+1xkxxk)2(1+2xkxk+1xxk+1)fk+1+(xkxk+1xxk+1)2(xxk)fk+(xk+1xkxxk)2(xxk+1)fk+1,  xkxxk+1,  k=0,1,,n1(3)该插值函数满足:

  1. 插值函数属于在区间 [ a , b ] [a,b] [a,b]上一阶导数连续的函数空间: I h ( x ) ∈ C 1 [ a , b ] I_h\left( x \right)\in C^1\left[a,b\right] Ih(x)C1[a,b]
  2. 插值函数在所有插值点的数值都等于原函数: I h ( x ) = f k ( k = 0 , 1 , ⋯ , n − 1 ) I_h\left( x \right)=f_k\left(k=0,1,\cdots,n-1\right) Ih(x)=fk(k=0,1,,n1)
  3. 插值函数一阶导数在所有插值点的数值都等于原函数一阶导数: I h ′ ( x ) = f k ′ ( k = 0 , 1 , ⋯ , n − 1 ) I_h^{'}\left( x \right)=f_k^{'}\left(k=0,1,\cdots,n-1\right) Ih(x)=fk(k=0,1,,n1)
  4. 插值函数在每个小区间上是三次多项式: I h ( x ) = a x 3 + b x 2 + c x + d I_h\left( x \right)=ax^3+bx^2+cx+d Ih(x)=ax3+bx2+cx+d

二、MATLAB

1.分段线性插值

% 分段线性插值
function [yOutArr]=func_PiecewiseLinearInterpolation(xInArr,yInArr,xQuery)% ************************************************************% 识别误差% ************************************************************xInLength=length(xInArr);yInLength=length(yInArr);% 插值数组不匹配if xInLength~=yInLengtherror('Error:The xInArr %d and the yInArr %d are not equal in length.',xInLength,yInLength);end% ************************************************************% 计算查询节点在插值函数上的函数值% ************************************************************% 只一个插值节点if xInLength==1yOutArr=yInArr;return;end% 有多个插值节点xQueryLength=length(xQuery);yOutArr=zeros(1,xQueryLength);pos=1;for i=1:1:xQueryLengthfor j=pos:1:xInLength-1% 查询节点如果超出插值节点范围则报错if xQuery(i)>xInArr(xInLength)||xQuery(i)<xInArr(1)error('Error:The num of the xQuery should gainer than %d and lesser than %d.',xInArr(1),xInArr(xInLength));end% 定位查询数组在插值节点的位置if (xQuery(i)>xInArr(j)&&xQuery(i)<xInArr(j+1))||(xQuery(i)==xInArr(j))pos=j;break;endend% 计算查询节点在插值函数上的函数值yOutArr(i)=polyval(func_LinearInterpolation(xInArr(pos),yInArr(pos),xInArr(pos+1),yInArr(pos+1)),xQuery(i));end
end

2.分段Hermit插值

% 分段三次Hermit插值
function [yOutArr]=func_PiecewiseCubeHermitInterpolation(xInArr,yInArr,dyInArr,xQuery)% ************************************************************% 识别误差% ************************************************************xInLength=length(xInArr);yInLength=length(yInArr);% 插值数组不匹配if xInLength~=yInLengtherror('Error:The xInArr %d and the yInArr %d are not equal in length.',xInLength,yInLength);end% ************************************************************% 计算查询节点在插值函数上的函数值% ************************************************************% 只一个插值节点if xInLength==1yOutArr=yInArr;return;end% 有多个插值节点xQueryLength=length(xQuery);yOutArr=zeros(1,xQueryLength);pos=1;for i=1:1:xQueryLengthfor j=pos:1:xInLength-1% 查询节点如果超出插值节点范围则报错if xQuery(i)>xInArr(xInLength)||xQuery(i)<xInArr(1)error('Error:The num of the xQuery should gainer than %d and lesser than %d.',xInArr(1),xInArr(xInLength));end% 定位查询数组在插值节点的位置if (xQuery(i)>xInArr(j)&&xQuery(i)<xInArr(j+1))||(xQuery(i)==xInArr(j))pos=j;break;endend% 计算查询节点在插值函数上的函数值yOutArr(i)=polyval(func_2dotsCubicHermitInterpolation(xInArr(pos:1:pos+1),yInArr(pos:1:pos+1),dyInArr(pos),dyInArr(pos+1)),xQuery(i));end
end

3.测试程序

% 测试分段低次插值函数——func_PiecewiseLinearInterpolatio、func_PiecewiseCubeHermitInterpolation
clc;
clear;
close all;x=-0.2*pi:0.2*pi:10*pi;
y=sin(x);
dy=diff(y,1);xq=0:0.01*pi:10*pi;
yq1=func_PiecewiseLinearInterpolation(x(2:1:length(x)),y(2:1:length(x)),xq);
yq2=func_PiecewiseCubeHermitInterpolation(x(2:1:length(x)),y(2:1:length(x)),dy,xq);
plot(x,y,'k*',xq,yq1,'r-',xq,yq2,'b-');

Alt

图2.1 分段线性与Hermit插值

总结

  以上在本文中对分段低次插值的两种常见方法的推导进行了简单介绍,并提供了MATLAB的实现代码与测试用例。

参考文献

[1]李庆扬,王能超,易大义. 数值分析.第5版[M]. 清华大学出版社, 2008.

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 怎么给USER新增表空间文件
  • c语言指针中“数组名的理解”以及“一维数组传参”的本质
  • 攻击服务器100G流量多少钱?攻击服务器1小时价格多少?
  • 使用RabbitMQ在Spring Boot入门实现简单的消息的发送与接收
  • TwinCAT3 新建项目教程
  • 8.Redis的List类型
  • 说说什么是变频空调及其工作原理
  • 软测面试二十问(最新面试)
  • 报表系统之Cube.js
  • 【mongodb】mongodb数据备份与恢复
  • 第十九天培训笔记
  • 职升网:中级经济师如何更好的选择专业?
  • Docker镜像仓库
  • R语言统计分析——自编函数
  • 盘点那些实用的开发技术!!
  • Android单元测试 - 几个重要问题
  • Apache Zeppelin在Apache Trafodion上的可视化
  • Apache的80端口被占用以及访问时报错403
  • CSS实用技巧
  • docker容器内的网络抓包
  • dva中组件的懒加载
  • gops —— Go 程序诊断分析工具
  • Java反射-动态类加载和重新加载
  • js如何打印object对象
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Linux CTF 逆向入门
  • passportjs 源码分析
  • 不上全站https的网站你们就等着被恶心死吧
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 浅谈web中前端模板引擎的使用
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • #100天计划# 2013年9月29日
  • (9)目标检测_SSD的原理
  • (Oracle)SQL优化技巧(一):分页查询
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (九)c52学习之旅-定时器
  • (算法)前K大的和
  • (微服务实战)预付卡平台支付交易系统卡充值业务流程设计
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • []串口通信 零星笔记
  • [001-03-007].第07节:Redis中的管道
  • [100天算法】-不同路径 III(day 73)
  • [14]内置对象
  • [24年新算法]NRBO-XGBoost回归+交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测
  • [Android] 240204批量生成联系人,短信,通话记录的APK
  • [android] 练习PopupWindow实现对话框
  • [android]-如何在向服务器发送request时附加已保存的cookie数据