C:查找值所属的bin索引

时间:2019-06-19 23:28:39

标签: c algorithm

我有一些垃圾箱,其范围呈指数增长。

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的索引。

有更聪明的方法吗?

2 个答案:

答案 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是最大的无符号值,不是计算得出的值。