我有以下定义:
typedef enum
{
def = 0,
m1 = 1,
m2 = 2,
m3 = 4,
m4 = 6,
m5 = 17,
m6 = 33,
m7 = 41,
m8 = 47,
m9 = 50,
m10 = 51,
m11 = 58,
m12 = 89,
m13 = 132,
m14 = 135
} my_enums;
我正在寻找一种最快的方法来检查函数的参数是否属于其中一个值m1..m14。显而易见的实现是if(p == m1 || p == m2 ...)或switch-case alternative。
有更快的东西吗? m1~m14的值是固定的,不能在连续的范围内。
感谢。
答案 0 :(得分:6)
我能想到的最快的是从0到135的字节数组。如果该项是您的有效枚举之一,则将值设置为1,如果不是,则将值设置为0。然后你可以写:
if (valuesArray[x])
YahooItsGood();
当然,如果您的范围很大,那么这不起作用。
如果传入的值可能超出该范围,那么您需要更多逻辑:
if (x >= 0 && x < 136 && valuesArray[x])
YahooItsGood();
当然,每个项目实际上只需要一个位,所以你可以使用一个1/8大小的数组来节省大量内存。测试值的逻辑变得更加复杂,但它仍然比一系列if / else或二进制搜索更快。
如果你有一个更大的集合,那么你可能想要构建一个哈希表。它不会像直接查找那么快,但是当值范围大得多时,它会使用更少的内存。
答案 1 :(得分:6)
switch语句是更好的选择。它有助于了解编译器可以使用的技巧使switch语句非常优化(在大多数情况下)。很多时候,比你自己想出的更好。
如果值不连续,则编译器可以求助于具有O(log(n))性能的静态二进制决策树。对于连续值列表,它将构造一个跳转表,即O(1)。相比之下,if-else结构是O(n)。
我建议你在使用其他方法之前完全理解你可以从switch语句中得到什么。
答案 2 :(得分:1)
一个简单的想法,如果你可以保证输入是8位宽:创建一个大小为256的静态int数组,在你的枚举指定的索引处为1,在其他地方为0。然后你要做的就是一次数组查找。
答案 3 :(得分:0)
if(p/7==0 && (p%6!=3 ||p%6!=5))
// p is present, p = 0,1,2,4,6
if(p==17||p==33.....remaining 7 numbers)
//p is present
所以你把它们从14个条件评估减少到12个...... 也许试着像我上面那样在价值观中找到一些关系。
答案 4 :(得分:0)
由于您需要最快的一个,因此位操作应该比字节快。
你可以有17个八位字节。对于每个位,如果该位是您想要的,则将其标记为1,否则为0.对于每次查找,只需计算Octet id和要检查的位,然后检查它并获得结果。
答案 5 :(得分:0)
我更喜欢二分搜索,因为值是有序的。
一个定义一个数组:
my_enums enumv[17] = {def, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, -1, -1};
(最后2个值是中心,它们对结果没有影响)。
然后进行二元搜索:
int s = 0;
for (int i = 8; i; i /= 2)
if (p >= enumv[s+i])
s += i;
if ( p >= 0 && p == enumv[s])
printf("Happy\n");
else
printf("Unhappy\n");
如果您不想要所有“for”的东西,并且由于您只有15个值,这个算法可以展开并“手头”编写,以便更快:
int s = 0;
s += 8*(p >= enumv[s+8]);
s += 4*(p >= enumv[s+4]);
s += 2*(p >= enumv[s+2]);
s += (p >= enumv[s+1]);
if (p >= 0 && p == enumv[s])
printf("Happy\n");
else
printf("Unhappy\n");
答案 6 :(得分:0)
我的2美分 - 在MSB上使用按位运算进行分而治之。看到32在这里接近中位数,首先将表格分成两半
if (p & 32)
下一级将错误情况与(p&amp; 4)进行比较,将真实情况与(p&amp; 64)进行比较 - 这使得每个分支中只有3个选项(可以由逻辑或者覆盖) ,除了32和64之间的一个,可以使用(p&amp; 48)进一步细分(这个不是2的圆幂,所以它只适用于某些情况,我想只有MSB相等)
这里的好处是你已经完成了二进制搜索(即使在你的数字是连续的最坏情况下,你在整个区域进行二进制搜索,仍然是log(MAX_N)),你正在做所以使用编译器可以预测的廉价按位运算(或者你可以继续自己做)