首页 > 编程知识 正文

python拉格朗日插值法,c语言实现线性插值

时间:2023-05-03 12:14:43 阅读:152735 作者:3565

这是非常简单的数学工具。 有些问题可能只需要简单的数学工具就能解决。

线性插值线性插值法是使用连接两个已知量的直线来确定两个已知量之间的一个未知量的值的方法。

线性插值与抛物线插值等其他插值方式相比,具有简单方便的特点。

线性插值可以用于逼近而不是原始函数,也可以用于在得到查找表的过程中计算表中没有的数值。它是实现精确快速查找表的一种非常好的方法。

将x0和x1中y=f(x )的值分别设为y0、y1,求出多项式:

y=1(x )=a0 a1 xy=(varphi_1) left ) x ) right ) a_0a_1xy=1 ) x )=a0a1x

满意:

1(x0 ),1 ) x1 )=y1(varphi_1) left ) x_0(right ),y_0,) varphi_1) left ) x_1) right

得到

y=1(x )=y0y1y0

x 1 − x 0 ( x − x 0 ) y=varphi _1left( x right) =y_0+frac{y_1-y_0}{x_1-x_0}left( x-x_0 right) y=φ1​(x)=y0​+x1​−x0​y1​−y0​​(x−x0​)

这样就能直接得到y。我们需要满足x在x0和x1之间。假设x不在x0和x1之间,公式也是满足,叫线性外插。

其实就是一个一元一次方程,y=kx+b,我们需要计算的就是斜率k,以及截距b。通过这个一元一次方程去计算区间内的x对应的y。

线性插值举例

ntc电阻测温度
ntc的温度曲线近似成一个数学表达式,但是需要用到math.h中的,占资源,计算慢。可以用线性插值的方法,比如只需要0-100度。保存一百个数据,以及对应的adc的值,之后根据测的adc进行插值。

速度规划
知道目标速度,加速度,根据这次速度反馈,设定下次速度给定。

分段pid
已知对应速度阈值的序列,以及对应pid的序列。根据速度反馈,或者速度给定,进行插值计算,让pid的更平滑。

图像里的线性插值,双线性插值,三线性插值。处理二维三维的图像

还很多。

程序设计 传入曲线的xy的表格利用二分法查找区间利用公式理计算区间内x的值

程序.h:

/*************************************************************** * @Copyright(C) 2020-2021, wangchongwei * @FileName: linear_interp.h * @Author: wangchongwei * @Version: 0.1.1 * @LastDate: 2021.8.14 ************************************************************/#ifndef _LINEAR_INTERP_H_#define _LINEAR_INTERP_H_#include <stdint.h>#ifdef __cplusplusextern "C" {#endifstruct LinearInterp{// 初始化曲线 void (*Init)(struct LinearInterp *self, float *arr_x, float *arr_y, uint32_t size); // 调用计算 float (*Cal)(struct LinearInterp *self, float val); float out; struct { float *arr_x; float *arr_y; int32_t size; }pvt;};void LinearInterp_Create(struct LinearInterp *self);#ifdef __cplusplus}#endif#endif /*************************************************************** * @Copyright(C) 2020-2021, wangchongwei * @FileName: linear_interp.c * @Author: wangchongwei * @Version: 0.1.1 * @LastDate: 2021.8.14 ************************************************************/#include "linear_Interp.h"#include "string.h"static void _Init(struct LinearInterp *self, float *arr_x, float *arr_y, uint32_t size){ self->pvt.arr_x = arr_x; self->pvt.arr_y = arr_y; self->pvt.size = size;}static float _Cal(struct LinearInterp *self, float val){ int32_t left = 0, mid = 0; int32_t right = self->pvt.size - 1; float x0,y0,x1,y1; // 二分法 while (left <= right) { mid = (left+right)/2; if (val<self->pvt.arr_x[mid]) right = mid - 1; else if (self->pvt.arr_x[mid] < val) left = mid + 1; else break; } // 头尾检测 if (mid == (self->pvt.size - 1)) { mid = mid-1; } else if (mid == 0){ mid = 0; } else{ mid = (self->pvt.arr_x[mid] <= val)?mid:mid-1; // 中间二分查找出现的情况 } // 3.Linear interpolation x0 = self->pvt.arr_x[mid]; y0 = self->pvt.arr_y[mid]; x1 = self->pvt.arr_x[mid+1]; y1 = self->pvt.arr_y[mid+1]; self->out = y0+(((y1-y0)*(val - x0))/(x1-x0)); return self->out;}void LinearInterp_Create(struct LinearInterp *self){ memset(self , 0 , sizeof(struct LinearInterp)); self->Init = _Init; self->Cal = _Cal;}

测试:

float arr_x[5] = {1,5,8,13,17}; float arr_y[5] = {4,45,10,40,20}; float res; LinearInterp_Create(&line_interp); line_interp.Init(&line_interp, arr_x,arr_y,5); res = line_interp.Cal(&line_interp,6); qDebug()<<"插值结果:"<<res; 插值结果: 33.3333

我按1的步长,从-10-30的区间进行插值,画图:

代码肯定还有很多优化的地方,计算时间,内存,效率。都应该考虑,但是在考虑都通用的情况下,必然会舍去一些。

比如优化:
提前计算出每个区间的斜率和截距。查找到后,只需要做一次乘法和加法。

gitee地址:
https://gitee.com/wang_chong_wei/qt_wave.git

被抛弃的写随笔公众号改写技术文章了,感兴趣的可以关注公众号:mldxt

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。