kir*_*off 3 binary operations numbers count representation
我正在寻找设置位计数问题的解决方案(给定二进制数,如何有效地计算设置的位数).
在这里,http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive,我找到了一些方法.
查找表方法怎么样?我不明白二进制表示/数字的哪些属性使它工作.
static const unsigned char BitsSetTable256[256] =
{
# define B2(n) n, n+1, n+1, n+2
# define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2)
# define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2)
B6(0), B6(1), B6(1), B6(2)
};
unsigned int v; // count the number of bits set in 32-bit value v
unsigned int c; // c is the total bits set in v
// Option 1:
c = BitsSetTable256[v & 0xff] +
BitsSetTable256[(v >> 8) & 0xff] +
BitsSetTable256[(v >> 16) & 0xff] +
BitsSetTable256[v >> 24];
// Option 2:
unsigned char * p = (unsigned char *) &v;
c = BitsSetTable256[p[0]] +
BitsSetTable256[p[1]] +
BitsSetTable256[p[2]] +
BitsSetTable256[p[3]];
// To initially generate the table algorithmically:
BitsSetTable256[0] = 0;
for (int i = 0; i < 256; i++)
{
BitsSetTable256[i] = (i & 1) + BitsSetTable256[i / 2];
}
Run Code Online (Sandbox Code Playgroud)
特别是,我BitsSetTable256最初并不理解这个定义.为什么定义这些数量B2,B4,......?在我看来,他们以后没有被使用过.
你能暗示二进制表示的进一步文档吗?
谢谢!
定义是按模式形成表格.它们是递归宏,B6使用B4而B4使用B2.B6(0)将被分解为:
B4(0), B4(1), B4(1), B4(2)
Run Code Online (Sandbox Code Playgroud)
B4(0)将被分解为:
0, 1, 1, 2
Run Code Online (Sandbox Code Playgroud)
序列的前几个数字将是:
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3
Run Code Online (Sandbox Code Playgroud)
如您所见,这些是为表中的每个索引设置的位数.
算法的其余部分是你将数字分成8位块并将每个块中设置的位数相加,这就是这些线的含义(根据自己的喜好使用选项1或选项2,而不是两者) :
// Option 1:
c = BitsSetTable256[v & 0xff] +
BitsSetTable256[(v >> 8) & 0xff] +
BitsSetTable256[(v >> 16) & 0xff] +
BitsSetTable256[v >> 24];
// Option 2:
unsigned char * p = (unsigned char *) &v;
c = BitsSetTable256[p[0]] +
BitsSetTable256[p[1]] +
BitsSetTable256[p[2]] +
BitsSetTable256[p[3]];
Run Code Online (Sandbox Code Playgroud)
底部的代码:
// To initially generate the table algorithmically:
BitsSetTable256[0] = 0;
for (int i = 0; i < 256; i++)
{
BitsSetTable256[i] = (i & 1) + BitsSetTable256[i / 2];
}
Run Code Online (Sandbox Code Playgroud)
是生成BitsSetTable256的另一种方法.它在运行时而不是在编译时生成表(这是宏定义的作用).
PS如果你的目标是足够的(SSE4)x86,你可以使用POPCNT指令.