如何在C(SDCC编译器)中用线性插值建立查找表
对于LPC922微控制器(带SDCC),我想创建一个带有线性插值的查找表。 假设我得到了x和y值,比如如何在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。。如果您没有找到正确的值,那么您有一个索引和一个相邻索引,然后使用您的公
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[]={300typedef结构{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 );
}