优化多重比较条件
Optimize multiple comparison conditions
我的主要代码需要比较一个整数 ASCII 命令,我想知道是否有优化的解决方案。
我可以在串行总线上从“1”发送到“128”,并到达正确的对象,我是这样做的:
// this is how I deal with the data sent on the serial bus
int translateASCII(char requestBuffer[10]){
char word[4] = {0};
word[0] = (int)requestBuffer[0];
word[1] = (int)requestBuffer[1];
word[2] = (int)requestBuffer[2];
int n = atoi(word);
return n;
}
void interpreteASCII(int ascii){
if (ascii > 0 && ascii < 33){
if (ascii < 9){
blabla
}
else if (ascii < 17){
blabla
}
else if (ascii < 25){
blabla
}
else
blabla
}
else if (ascii < 65){
if (ascii < 41){
blabla
}
else if { ... }
}
}
所以我正在寻找一种方法来优化这个 'architecture'。还考虑了 switch case 函数,但它似乎只将我的 ASCII 变量与单个整数进行比较,如:
switch (ascii){
case '8':
blabla
这不是我要找的,因为指令实际上取决于 ASCII 变量,它按 32 的间隔排序,它们本身必须按 8 个值的间隔排序。
你说每个 8 的间隔需要一个案例,例如1-8、9-16 等。试试这个:
switch ((ascii + 7)/ 8) {
case 0: // input was zero
break;
case 1: // input was in [1..8]
break;
// ...
case 8: // input was in [57..64]
break;
}
首先,去掉 int
并用 char
或 uint8_t
替换它。您的符号 table 似乎不太可能带有负索引。
接下来,您基本上是在检查某些内容是否在特定时间间隔内。使用 if-else 做到这一点的最不有效的方法是按升序进行:
if(ascii < 17)
...
else if(ascii < 25)
...
else if(ascii < 33)
...
显然 "magic numbers" 应该替换为常量或字符文字。
如果间隔为 8(那是 而不是 您的幻数给出的值),您可以通过执行 ascii / 8
作为查找来提高性能。通过普通开关或通过函数指针查找。后者的例子:
#include <stdio.h>
#include <stdint.h>
void f0_7 (uint8_t n) { printf("%d %s\n", n, __func__); }
void f8_15 (uint8_t n) { printf("%d %s\n", n, __func__); }
void f16_23 (uint8_t n) { printf("%d %s\n", n, __func__); }
... // up to 127
void interpreteASCII(uint8_t ascii)
{
typedef void(lookup_func)(uint8_t);
lookup_func* const LOOKUP[] = { f0_7, f8_15, f16_23, ... /* up to 127 */ };
LOOKUP[ascii/8](ascii);
}
int main (void)
{
for(uint8_t i=0; i<24; i++)
{
interpreteASCII(i);
}
return 0;
}
(在调用这样的 table 查找之前进行一些边界检查是个不错的主意。)
不清楚 'optimize' 是什么意思。
您希望它的内存占用尽可能小吗?那么 John Zwinck 的回答(或类似的回答)可能是您最好的选择。
你想让它尽快 运行 吗?那么由 128 个条目(其中许多包含相同的值)组成的查找 table 将是最好的方法。
您希望它尽可能易于阅读和理解吗?那么没有什么比您已经想出的解决方案更好的了。
我的主要代码需要比较一个整数 ASCII 命令,我想知道是否有优化的解决方案。
我可以在串行总线上从“1”发送到“128”,并到达正确的对象,我是这样做的:
// this is how I deal with the data sent on the serial bus
int translateASCII(char requestBuffer[10]){
char word[4] = {0};
word[0] = (int)requestBuffer[0];
word[1] = (int)requestBuffer[1];
word[2] = (int)requestBuffer[2];
int n = atoi(word);
return n;
}
void interpreteASCII(int ascii){
if (ascii > 0 && ascii < 33){
if (ascii < 9){
blabla
}
else if (ascii < 17){
blabla
}
else if (ascii < 25){
blabla
}
else
blabla
}
else if (ascii < 65){
if (ascii < 41){
blabla
}
else if { ... }
}
}
所以我正在寻找一种方法来优化这个 'architecture'。还考虑了 switch case 函数,但它似乎只将我的 ASCII 变量与单个整数进行比较,如:
switch (ascii){
case '8':
blabla
这不是我要找的,因为指令实际上取决于 ASCII 变量,它按 32 的间隔排序,它们本身必须按 8 个值的间隔排序。
你说每个 8 的间隔需要一个案例,例如1-8、9-16 等。试试这个:
switch ((ascii + 7)/ 8) {
case 0: // input was zero
break;
case 1: // input was in [1..8]
break;
// ...
case 8: // input was in [57..64]
break;
}
首先,去掉 int
并用 char
或 uint8_t
替换它。您的符号 table 似乎不太可能带有负索引。
接下来,您基本上是在检查某些内容是否在特定时间间隔内。使用 if-else 做到这一点的最不有效的方法是按升序进行:
if(ascii < 17)
...
else if(ascii < 25)
...
else if(ascii < 33)
...
显然 "magic numbers" 应该替换为常量或字符文字。
如果间隔为 8(那是 而不是 您的幻数给出的值),您可以通过执行 ascii / 8
作为查找来提高性能。通过普通开关或通过函数指针查找。后者的例子:
#include <stdio.h>
#include <stdint.h>
void f0_7 (uint8_t n) { printf("%d %s\n", n, __func__); }
void f8_15 (uint8_t n) { printf("%d %s\n", n, __func__); }
void f16_23 (uint8_t n) { printf("%d %s\n", n, __func__); }
... // up to 127
void interpreteASCII(uint8_t ascii)
{
typedef void(lookup_func)(uint8_t);
lookup_func* const LOOKUP[] = { f0_7, f8_15, f16_23, ... /* up to 127 */ };
LOOKUP[ascii/8](ascii);
}
int main (void)
{
for(uint8_t i=0; i<24; i++)
{
interpreteASCII(i);
}
return 0;
}
(在调用这样的 table 查找之前进行一些边界检查是个不错的主意。)
不清楚 'optimize' 是什么意思。
您希望它的内存占用尽可能小吗?那么 John Zwinck 的回答(或类似的回答)可能是您最好的选择。
你想让它尽快 运行 吗?那么由 128 个条目(其中许多包含相同的值)组成的查找 table 将是最好的方法。
您希望它尽可能易于阅读和理解吗?那么没有什么比您已经想出的解决方案更好的了。