linear_Interp线性插值

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


#include "stdio.h"
#include "stdint.h"

/***************************************************************
 * @Copyright(C)    2020-2021,
 * @FileName:       线性插值
 * @Author:         kane
 * @Version:        0.1.1
 * @LastDate:       2021.8.14
 ************************************************************/
#ifndef _LINEAR_INTERP_H_
#define _LINEAR_INTERP_H_
#include <stdint.h>

struct LinearInterp
{
    // 初始化曲线
    void (*Init)(struct LinearInterp *self, float *arr_x, float *arr_y, float *arr_k, float *arr_b, uint32_t size);
    // 调用计算
    float (*Cal)(struct LinearInterp *self, float val);

    float out;

    struct
    {
        float *arr_x; //x0,x1,x2
        float *arr_y; //y0,y1,y2
        float *s_k;   //斜率
        float *s_b;   //截距
        int32_t size; //点的数量
    } pvt;
};

void LinearInterp_Create(struct LinearInterp *self);

#endif
/***************************************************************
 * @Copyright(C)    2020-2021,
 * @FileName:       线性插值
 * @Author:         kane
 * @Version:        0.1.1
 * @LastDate:       2021.8.14
 ************************************************************/

#include "linear_Interp.h"
#include "string.h"
#include <stdlib.h>

//初始化函数,动态绑定x,y,k,b,size,并计算k,b
static void _Init(struct LinearInterp *self, float *arr_x, float *arr_y, float *arr_k, float *arr_b, uint32_t size)
{
    self->pvt.arr_x = arr_x;
    self->pvt.arr_y = arr_y;
    self->pvt.s_k = arr_k;
    self->pvt.s_b = arr_b;
    self->pvt.size = size;

    for (uint32_t i = 0; i < (size - 1); ++i)
    {
        self->pvt.s_k[i] = (float)(self->pvt.arr_y[i] - self->pvt.arr_y[i + 1]) / (self->pvt.arr_x[i] - self->pvt.arr_x[i + 1]);
        self->pvt.s_b[i] = (float)(self->pvt.arr_y[i] - self->pvt.s_k[i] * self->pvt.arr_x[i]);
    }
}

//插值计算
static float _Cal(struct LinearInterp *self, float val)
{
    int32_t left = 0, mid = 0;
    int32_t right = self->pvt.size - 1;

    float x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0;

    // 二分法
    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 方法1
    /*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));
	printf("out1 = %f\n", self->out);*/

    //方法2
    printf("out2 = %f\n", (self->pvt.s_k[mid] * val) + (self->pvt.s_b[mid]));
    self->out = (self->pvt.s_k[mid] * val) + (self->pvt.s_b[mid]);
    return self->out;
}

//创建一个插值句柄,动态绑定函数
void LinearInterp_Create(struct LinearInterp *self)
{
    memset(self, 0, sizeof(struct LinearInterp));

    self->Init = _Init;
    self->Cal = _Cal;
}

// //demo
// int main(void)
// {
//     LinearInterp line_interp = {0};
//     float arr_x[5] = {1, 5, 8, 13, 17};
//     float arr_y[5] = {4, 45, 10, 40, 20};
//     float arr_k[sizeof(arr_x) / sizeof(arr_x[0]) - 1] = {0}; //这个自动计算填充 斜率
//     float arr_b[sizeof(arr_x) / sizeof(arr_x[0]) - 1] = {0}; //这个自动计算填充 截距
//     LinearInterp_Create(&line_interp);
//     line_interp.Init(&line_interp, arr_x, arr_y, arr_k, arr_b, 5);

//     float res = line_interp.Cal(&line_interp, 2);

//     return 0;
// }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值