我有一些垃圾箱,其范围呈指数增长。
Bin 0 -> [0 <= x <= 10] (interval = 10)
Bin 1 -> [11 <= x <= 30] (interval = 20)
Bin 2 -> [31 <= x <= 70] (interval = 40)
Bin 3 -> [71 <= x <= 150] (interval = 80)
Bin 4 -> [151 <= x <= 310] (interval = 160)
...等等。
bin的数量和第一个间隔是事先已知的(在这种情况下,分别为5和10)。 x
的最低可能值为0。
我当前正在做的是一个标准的for循环,每次乘以2,然后如果value
在范围内,则返回bin的索引。
有更聪明的方法吗?
答案 0 :(得分:2)
如“风向标”所建议,
bin = floor( log2 ( (value + 9) / 10 ))
还:
bin = floor( log2 ( floor( (value + 9) / 10 ) ))
C中的整数除法(i1 / i2)等于trunc(i1 / i2)(截断为零),对于非负整数,它等于floor(i1 / i2),因此无需实现内层。
floor(log2(i))可以非常有效地实现。有关快速的32位和64位整数实现,请参见accepted answer here。
以下是代码( int 为32位时有效)。 OnlineGDB
#include <stdio.h>
const unsigned int tab32[32] = {
0, 9, 1, 10, 13, 21, 2, 29,
11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7,
19, 27, 23, 6, 26, 5, 4, 31};
unsigned int log2_32(unsigned int value)
{
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return tab32[(value * 0x07C4ACDD) >> 27];
}
int main()
{
unsigned int value = 151;
unsigned int bin = 0;
if (value > 0)
bin = log2_32( (value + 9) / 10 );
printf("value: %u, bin: %u", value, bin);
return 0;
}
答案 1 :(得分:1)
对数算法很酷,但是您也可以只建立一个表并使用二进制搜索来找到bin。
Linking.openSettings();
循环永远不会运行超过五次迭代,因此它非常快。 Bin 28是最大的无符号值,不是计算得出的值。