我知道这是计算整数中数字设置位的相当不错的解决方案:
CountBits(n)
count = 0
while n > 0
n ← n & (n - 1)
count ← count + 1
是否存在计算有多少非重叠k位组非零的类似优雅解决方案。我目前有:
CountGroups(n, k)
count = 0
mask = (2 << k) - 1
while n > 0
if n & mask ≠ 0
count ← count + 1
n >> k
在最左边的组的位置是线性的。在后一种算法中,如果只设置了第一组和最后一组,我必须访问并检查其间的所有组,而前者只执行两次操作。它不是瓶颈或任何东西,只是好奇是否有更好的方法。
答案 0 :(得分:1)
通过将字分割为奇数和偶数序列,可以并行计算k个设置位组。当且仅当组中的所有位都已设置时,将携带到下一个空位置(标有...)。
最初的问题是关于在一个组中设置的任何位,但这可以通过补充 n ,添加一个并补充结果来进行转换。 (现在结果== 1当且仅当原始组全部为零时。)
// ...xxx...xxx...xxx even sequence
// yyy...yyy...yyy... odd sequence
uint64_t a = ~n & even_mask; // inverse of n
uint64_t b = (~n >> k) & even_mask; // inverse of n
a += 0010101; // this is octal, where a "one" is added to each group
b += 0010101; // same for odd sequence
// a = 001xxx000yyy001xxx -- e.g. first and last group were all ones
// b = 000yyy000yyy001yyy -- e.g. last group of 'y' was all one
a &= ~even_mask; // remove the xxx yyy parts, leaving only carry
b &= ~even_mask;
a |= (b << 1);
return bitcount(a ^ 03030303); // return total number of carry bits
Bitcount可以并行完成,如果有的话可以使用特殊指令(__popcount)或者使用Kerningham Richie -method(n&amp;(n-1))。
这只说明了k == 3,但可以扩展到任意k,即使当k变大时兴趣的回报会减少。
根据 k ,可能有更好的算法来为条件派生布尔表达式。
在这种情况下,对于每个组,条件是n(i)| n(i + 1)| ... n(i + k-1),可以并行和/或使用折叠技术进行评估,当k是2的幂时,这种技术特别有用。
// n = aabb ccdd eeff gghh iijj -- original sequence, k = 4
// 0011 0011 0011 0011 0011 -- mask
n = (n | (n >> 2)) & 0x33333333; // fold to aa|bb, cc|dd, etc.
n = (n | (n >> 1)) & 0x11111111; // fold boolean expression as 0th bit position in each group
return bitcount(n);