C++ 如何将所有设定位向右移动?

C++ 如何将所有设定位向右移动?,c++,c,bit-manipulation,C++,C,Bit Manipulation,问题:如何开发将32位整数中的所有设定位(1)向右移位的算法 范例 V= 0b01001000110010 V包含5个设置位,如果我们将它们向右移动,则得到: V = 0b011111 我所尝试的: v = v - ((v >> 1) & 0x55555555); // reuse input as temporary v = (v & 0x33333333) + ((v >> 2) & 0x333333

问题:如何开发将32位整数中的所有设定位(
1
)向右移位的算法

范例

V= 0b01001000110010 
V
包含5个设置位,如果我们将它们向右移动,则得到:

V = 0b011111
我所尝试的:

v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
上述代码返回32位整数中的设置位数

并使用以下代码

c = (1<<c) - 1;

c=(1
您可以使用
V>=1;
intv=(V>>1);
您不能吗

如果目的是将所有非零位向右移动到all,那么您可以这样做

int v = 0;
int i;

for( i = 0; i < 32; i++, V >>= 1 )
   if( (V & 1) != 0 )
      v = (v << 1) + 1;

V = v;
intv=0;
int i;
对于(i=0;i<32;i++,V>>=1)
如果((V&1)!=0)

v=(v您可以尝试找到一个神奇常数,并使用乘法和右移(32-5)(假设您使用32位整数存储常数)

#包括
int main()
{
无符号V=0b01001000110010;
unsigned magic=0x79838cb2;//尝试一些随机数,直到成功为止
无符号结果=(V*magic)>>(32-5);
std::cout
bitset const bv(V);
size_t const numSetBits=bv.count();

uint32\u t const answer=~(~0U这将对某些值
v
执行此操作

// Count the bits (only iterates once per set bit)
unsigned count = 0;
for(; v!=0; v&=(v-1))
    ++count;

// Produce that many "shifted bits".
v = (1 << count) - 1;
//对位进行计数(每个设置位仅迭代一次)
无符号计数=0;
对于(;v!=0;v&=(v-1))
++计数;
//产生那么多的“移位位”。

v=(1我建议使用两个变量:

unsigned int Squish_Bits(unsigned int value)
{
  unsigned int result = 0;
  for (i = 0; i < sizeof(value)/CHAR_BITS; ++i)
  {
    if (value & (1 << i))
    {
       result <<= 1;
       result |= 1;
    }
  }
  return result;
}
无符号整数压缩位(无符号整数值)
{
无符号整数结果=0;
对于(i=0;iint v=0b01001000110010;
int a=0;
对于(int i=0;i<32;++i){
如果((v&1)==1)
a=(a>1;
}
v=a;

我看到的最佳解决方案是使用总体计数来获得1位的数量,然后只使用
(1
int shift(int V){
如果(V!=0){
int r=1;
对于(int i=0;i<32;i++)

如果((V>>i)和1)r你用这个做什么?你想数一数1位吗?这不会从
0B010010000110010
产生
0b011111
。嗯……所以目的是将所有1位一直向右移动?我没有这样读问题,坦白说,我现在不相信我会这样做。编辑以允许将所有1位一直向右移动右v不是常数。我在寻找通用算法。输入是v,输出是移位到右v的设定位right@MOHAMED好的,那么Arun Saha的解决方案就是你可以使用的。我将把这个答案留给以后需要常数V的人参考。这是一个很好的通用解决方案。OP可以看看
bit的实现set::count
在他的标准库中,如果他好奇的话。旁白:如果
count()
是您使用它的全部目的,那么您最好将
位集设置为常量。我认为
(请注意,如果输入设置了所有位,则此操作将失败(如此大的移位量是未定义的行为)@Marglisse你能解释一下为什么它是未定义的行为吗?因为它在标准中这么说(因为一些处理器将取代a@MOHAMED:谢谢。Marc Glisse:你能提供一些关于未定义行为情况的参考吗?
// Count the bits (only iterates once per set bit)
unsigned count = 0;
for(; v!=0; v&=(v-1))
    ++count;

// Produce that many "shifted bits".
v = (1 << count) - 1;
unsigned int Squish_Bits(unsigned int value)
{
  unsigned int result = 0;
  for (i = 0; i < sizeof(value)/CHAR_BITS; ++i)
  {
    if (value & (1 << i))
    {
       result <<= 1;
       result |= 1;
    }
  }
  return result;
}
int v = 0b01001000110010;
int a = 0;

for (int i = 0; i < 32; ++i) {
    if((v & 1) == 1)
       a = (a << 1) + 1;

    v = v >> 1;
}

v = a;
int shift(int V) {
    if (V != 0) {
        int r = 1;
        for (int i = 0; i < 32; i++)
            if ((V >> i) & 1) r <<= 1;
        return r - 1;
    } else return 0;
}