【发布时间】:2013-11-18 18:16:24
【问题描述】:
如果我在 c++ 中有long long x;,我如何遍历数字中的每个位以检查它是零还是 1?
我想计算位中的个数。
【问题讨论】:
-
如果只是你想要的计数,还有更快的方法。在stackoverflow.com/questions/109023/… 中讨论。请注意,其中一些方法需要长时间更改。
如果我在 c++ 中有long long x;,我如何遍历数字中的每个位以检查它是零还是 1?
我想计算位中的个数。
【问题讨论】:
你需要使用移位>>操作符:
unsigned long long x = static_cast<unsigned long long>(your_value);
//unsigned long long fix for issue pointed out by @Zac Howland in comments
unsigned int count = 0;//number of 1 bits
while (x != 0)
{
unsigned long long bit = x & 1;
if( bit == 1 )
{
count ++;//...
}
else //zero
{
//...
}
x >>= 1;
}
还有其他方法可以通过各种方式执行此操作,您可以找到它们here (along with other stuff)
【讨论】:
x 是否定的,您可能会遇到的一个问题(实现定义)。一些实现通过保持负数来实现负数的右移,所以你永远不会得到x == 0。
你不需要做移位操作。:)
size_t count = 0;
for ( long long v = x; v; v &= v - 1 ) ++count;
【讨论】:
v &= v - 1 基本上是一个右移,对吧? :-P
1111,那么每次迭代基本上都和<< 1一样。如果你有1001,第一次迭代基本上是<< 3。它仍然是有效的右移 - 只是由定位决定的可变数量的移位。不过,对于位计数,您完全可以不使用循环。
const unsigned int BITCOUNT = sizeof(long long) * CHAR_BIT - 1;
// or
const unsigned int BITCOUNT = sizeof(unsigned long long) * CHAR_BIT;
for (unsigned int i = 0; i < BITCOUNT; ++i)
{
unsigned int test_bit = 1LL << i;
if (value & test_bit)
{
// do something
}
}
如果只需要位数,可以使用 SWAR 算法:
unsigned int bit_count(unsigned long long i)
{
i = i - ((i >> 1) & 0x5555555555555555);
i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
return (((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) >> 56;
}
【讨论】:
CHAR_BIT)
以下程序显示了用于循环一个字节的过程
#include <iostream>
int main()
{
std::uint_fast8_t flags{ 0b10011000 };
for (int i = 128; i >= 1; i /= 2)
{
if (flags & i)
std::cout << '1';
else
std::cout << '0';
}
std::cout << '\n';
return 0;
}
这个打印:10011000
【讨论】: