如何在C(SDCC编译器)中用线性插值建立查找表

如何在C(SDCC编译器)中用线性插值建立查找表,c,linear-interpolation,C,Linear Interpolation,对于LPC922微控制器(带SDCC),我想创建一个带有线性插值的查找表。 假设我得到了x和y值,比如 x=300 y=10,0201 x=700 y=89,542 x=800 y=126,452 x=900 y=171,453 x=1500 y=225,123 使用线性插值的查找表的代码是什么样子的,因此我得到了y的正确值((171453+126452)/2),例如x=850?将所有值放在一个数组中。然后搜索x。。如果您没有找到正确的值,那么您有一个索引和一个相邻索引,然后使用您的公

对于LPC922微控制器(带SDCC),我想创建一个带有线性插值的查找表。 假设我得到了x和y值,比如

x=300 y=10,0201 
x=700 y=89,542 
x=800 y=126,452 
x=900 y=171,453 
x=1500 y=225,123

使用线性插值的查找表的代码是什么样子的,因此我得到了y的正确值((171453+126452)/2),例如x=850?

将所有值放在一个数组中。然后搜索x。。如果您没有找到正确的值,那么您有一个索引和一个相邻索引,然后使用您的公式计算该值。

double get_value(double x)
double get_value(double x)
{
    /* NOTE: xs MUST be sorted */
    static const double xs[] = { 300, 700, 800, 900, 1500 };
    static const double ys[] = { 10.0201, 89.542, 126.452, 171.453, 225.123 };

    /* number of elements in the array */
    static const int count = sizeof(xs)/sizeof(xs[0]);

    int i;
    double dx, dy;

    if (x < xs[0]) {
        /* x is less than the minimum element
         * handle error here if you want */
        return ys[0]; /* return minimum element */
    }

    if (x > xs[count-1]) {
        return ys[count-1]; /* return maximum */
    }

    /* find i, such that xs[i] <= x < xs[i+1] */
    for (i = 0; i < count-1; i++) {
        if (xs[i+1] > x) {
            break;
        }
    }

    /* interpolate */
    dx = xs[i+1] - xs[i];
    dy = ys[i+1] - ys[i];
    return ys[i] + (x - xs[i]) * dy / dx;
}
{ /*注意:xs必须进行排序*/ 静态常数double xs[]={3007008009001500}; 静态常数双ys[]={10.0201,89.542,126.452,171.453,225.123}; /*数组中的元素数*/ 静态常量int count=sizeof(xs)/sizeof(xs[0]); int i; 双dx,dy; if(xxs[count-1]){ 返回ys[count-1];/*返回最大值*/ } /*求i,使xs[i]x){ 打破 } } /*插入*/ dx=xs[i+1]-xs[i]; dy=ys[i+1]-ys[i]; 返回ys[i]+(x-xs[i])*dy/dx; }
如果您愿意,这可以相当容易地扩展到其他应用程序。请注意,您可能需要扩展边境地区的特殊情况,无论您希望如何处理。常用的方法是在没有足够的相邻值可用于首选方法时进行线性插值

另外,当值的数量开始增长时,我建议使用一种方法来计算起点。但这几个值不应该是问题

更新:由于OP在一个有限的平台上工作,以下是上述版本:

/*注意:xs必须排序*/
静态常量fix16_t xs[]={300
typedef结构{double x;double y;}坐标;
协调委员会[5]=
{
{300, 10.02},
{700, 89.542},
{800, 126.452}, 
{900, 171.453}, 
{1500,225.123}
};    
双内点(坐标,双x,内点n)
{
int i;
对于(i=0;i
但是如果我找不到正确的值,如何找到索引和相邻索引?@Stefan:浏览SDCC手册,它看起来只支持浮点。在这种情况下,所有的
声明都应该更改为
浮点
,所有常量都应该有
.0f
或简单地添加
f
rse您可能还想改用定点算法。第一次尝试时,我将其更改为int,只是没有点的固定值。您的解决方案的问题是Eclipse会说:?ASlink错误无法在内部RAM中为区域DSEG获取534个连续字节。at 1:警告119:不知道如何处理文件“”。文件扩展名在不支持的make上:**[test.hex]错误1生成:由于错误,目标'all'没有重新生成。如果我只使用4个或更少的值,这是可以的,但如果我使用更多的值,则似乎没有足够的RAM。您甚至可以将最后一个索引存储在静态变量中,并从这一点开始搜索,因为通常线性插值例程是以顺序方式调用的。@Stefan:看起来它可能将数据放在r/w段而不是只读段中。请尝试将
xs
ys
移动到函数外部,尽管我怀疑这是否会有帮助。@user786653非常感谢,这似乎很有效。现在我得到了µC的十六进制文件,但目前它仍然无法正常工作。但我会尝试我想知道,谢谢
/* NOTE: xs MUST be sorted */
static const fix16_t xs[] = { 300<<16, 700<<16, 800<<16, 900<<16, 1500<<16 };
static const fix16_t ys[] = { (fix16_t)(65536.0*10.0201+0.5), (fix16_t)(65536.0*89.542+0.5), (fix16_t)(65536.0*126.452+0.5), (fix16_t)(65536.0*171.453+0.5), (fix16_t)(65536.0*225.123+0.5) };

fix16_t get_value_fix(fix16_t x)
{    
    /* number of elements in the array */
    static const int count = sizeof(xs)/sizeof(xs[0]);
    int i;
    fix16_t dx, dy;

    if (x < xs[0]) {
        /* x is less than the minimum element
         * handle error here if you want */
        return ys[0]; /* return minimum element */
    }

    if (x > xs[count-1]) {
        return ys[count-1]; /* return maximum */
    }

    /* find i, such that xs[i] <= x < xs[i+1] */
    for (i = 0; i < count-1; i++) {
        if (xs[i+1] > x) {
            break;
        }
    }

    /* interpolate */
    dx = fix16_sub(xs[i+1], xs[i]);
    dy = fix16_sub(ys[i+1], ys[i]);
    return fix16_add(ys[i],  fix16_div(fix16_mul(fix16_sub(x, xs[i]), dy), dx));
}
typedef struct { double x; double y; } coord_t;

coord_t c[5] = 
{
    {300, 10.02},
    {700, 89.542},
    {800, 126.452}, 
    {900, 171.453}, 
    {1500,225.123}
};    

double interp( coord_t* c, double x, int n )
{
    int i;

    for( i = 0; i < n-1; i++ )
    {
        if ( c[i].x <= x && c[i+1].x >= x )
        {
            double diffx = x - c[i].x;
            double diffn = c[i+1].x - c[i].x;

            return c[i].y + ( c[i+1].y - c[i].y ) * diffx / diffn; 
        }
    }

    return 0; // Not in Range
}

int main(int argc, char** argv) 
{
    double y = interp( c, 850, 5 );
}