如何在大型值列表中搜索值
How to search for value in large list of values
我的程序中有电阻输出。现在我想把它转换成温度。因此,为此我有一个电阻值列表及其相应的温度,该列表有 400 个值。我正在为我的 AVR 微控制器在嵌入式 C 中对其进行编程。
我正在考虑用 for 循环创建一个函数,但是值的数量非常多,所以这不是一个好主意。
我希望如果我给出的电阻为 70 欧姆,那么该函数或程序应该在该列表中检查 70 欧姆的温度。
最好的方法可能是使用字典,但 C 本身没有字典,因此您需要自己实现一个。也许看这里:Quick Way to Implement Dictionary in C
400 不是很多,所以即使遍历它也应该没问题。
所以您正在使用查找 table 将电阻转换为温度。您有一个包含 400 个条目的 table。您可以使用 nearest-neighbor 算法,您只需编写一个 for
循环并查找电阻值与测量电阻最接近的 table 条目,然后报告存储在其中的温度table条目。
但是,您可以做得更好。如果按阻力对查找 table 进行排序,则可以使用 linear interpolation 来提供更准确的转换。这意味着您找到测量电阻介于两者之间的两个条目。然后在这些条目之间进行插值(使用算术按比例计算 table 条目之间的温度)以获得更准确的温度转换。
下面是How to build a lookup table in C (SDCC compiler) with linear interpolation中线性插值的例子。
我会采用您拥有的 400 个数据点,将它们放入您选择的 excel/program 中,并生成一个回归函数(如果它对温度有抵抗力,则可能是线性的)。
如果您担心速度,AVR 有时会有 L/S、MUL 和 ADD 的管道,因此计算速度可能比查找速度更快。
等距表x-values常用于嵌入式系统。
如果您当前的 table 电阻值 (x) 不等距,请使用台式计算机 calculate/interpolate 等距电阻值的温度值 (y)。
然后您可以使用一个简单的温度值数组并根据电阻计算指数。
示例table,假设您的电阻范围为 80 到 110,相应的温度范围为 0 到 100。
resistance temperature (corresponding table index)
80 0 0
82 1 1
84 2 2
86 4 3
88 7 4
... ...
108 99 29
110 100 30
然后你可以使用这样的数组
int temp_table[] = { 0, 1, 2, 4, 7, /* ... */ 99, 100 };
并像这样计算温度:
const int rmin = 80;
const int rmax = 110;
int r; /* assuming this is the measures resistance */
int temp;
int index;
if(r < rmin) {
/* error min */
} else if(r > rmax) {
/* error max */
} else {
/* This calculates the table index for the highest resistance value
from the table not greater than r. Check your resistance range
and factor and divider to make sure you don't get an overflow here. */
index = ( (r - rmin) * (sizeof(temp_table) / sizeof(temp_table[0])) ) / (rmax - rmin);
temp = temp_table(index);
}
如果您的 table 点较少,您可能希望使用线性(或其他)插值法扩展这个简单的 table 搜索。
我的程序中有电阻输出。现在我想把它转换成温度。因此,为此我有一个电阻值列表及其相应的温度,该列表有 400 个值。我正在为我的 AVR 微控制器在嵌入式 C 中对其进行编程。
我正在考虑用 for 循环创建一个函数,但是值的数量非常多,所以这不是一个好主意。
我希望如果我给出的电阻为 70 欧姆,那么该函数或程序应该在该列表中检查 70 欧姆的温度。
最好的方法可能是使用字典,但 C 本身没有字典,因此您需要自己实现一个。也许看这里:Quick Way to Implement Dictionary in C
400 不是很多,所以即使遍历它也应该没问题。
所以您正在使用查找 table 将电阻转换为温度。您有一个包含 400 个条目的 table。您可以使用 nearest-neighbor 算法,您只需编写一个 for
循环并查找电阻值与测量电阻最接近的 table 条目,然后报告存储在其中的温度table条目。
但是,您可以做得更好。如果按阻力对查找 table 进行排序,则可以使用 linear interpolation 来提供更准确的转换。这意味着您找到测量电阻介于两者之间的两个条目。然后在这些条目之间进行插值(使用算术按比例计算 table 条目之间的温度)以获得更准确的温度转换。
下面是How to build a lookup table in C (SDCC compiler) with linear interpolation中线性插值的例子。
我会采用您拥有的 400 个数据点,将它们放入您选择的 excel/program 中,并生成一个回归函数(如果它对温度有抵抗力,则可能是线性的)。
如果您担心速度,AVR 有时会有 L/S、MUL 和 ADD 的管道,因此计算速度可能比查找速度更快。
等距表x-values常用于嵌入式系统。
如果您当前的 table 电阻值 (x) 不等距,请使用台式计算机 calculate/interpolate 等距电阻值的温度值 (y)。
然后您可以使用一个简单的温度值数组并根据电阻计算指数。
示例table,假设您的电阻范围为 80 到 110,相应的温度范围为 0 到 100。
resistance temperature (corresponding table index)
80 0 0
82 1 1
84 2 2
86 4 3
88 7 4
... ...
108 99 29
110 100 30
然后你可以使用这样的数组
int temp_table[] = { 0, 1, 2, 4, 7, /* ... */ 99, 100 };
并像这样计算温度:
const int rmin = 80;
const int rmax = 110;
int r; /* assuming this is the measures resistance */
int temp;
int index;
if(r < rmin) {
/* error min */
} else if(r > rmax) {
/* error max */
} else {
/* This calculates the table index for the highest resistance value
from the table not greater than r. Check your resistance range
and factor and divider to make sure you don't get an overflow here. */
index = ( (r - rmin) * (sizeof(temp_table) / sizeof(temp_table[0])) ) / (rmax - rmin);
temp = temp_table(index);
}
如果您的 table 点较少,您可能希望使用线性(或其他)插值法扩展这个简单的 table 搜索。