使用相同数量的设置位查找下一个更大的数字

时间:2014-10-27 19:04:43

标签: c algorithm bit-manipulation

我正在研究一个问题,我给出了一个数字n,我必须找到具有相同设置位数的下一个更大的元素。在互联网上搜索时,我发现了一段有趣的代码,用几行代码(BIT MAGIC)here完成了这个:

unsigned nexthi_same_count_ones(unsigned a) {
  /* works for any word length */
  unsigned c = (a & -a);
  unsigned r = a+c;
  return (((r ^ a) >> 2) / c) | r);
}

但我想了解它将始终有效的算法的基本逻辑。所有边界案件都将得到妥善处理。

有人可以通过简单的步骤解释逻辑。

由于

2 个答案:

答案 0 :(得分:1)

在下一个较高的数字中,最右侧1个交换的最左侧1位于其左侧的0,而剩余的1移动到最右边。

  • 代码隔离最低1
  • 将其添加到a(使得携带波动到下一个更高的0,反转所有这些位)
  • 前 - 或获得最不重要的一个,向左延伸一个位置。
  • 向右移动两个位置使其左边界位于原始位置的右侧一个位置 (从高位留下那个0的地方),
  • 除以最低10的右端提供了更多a位的空间。

答案 1 :(得分:0)

假设我们有一些比特模式,例如

111100111 - 以十进制表示487

生成下一个最高整数,同时保留0&1和1的数量,如输入中我们需要找到输入右边的前0位,然后是1,并且我们需要将此位切换为1.然后我们需要将此翻转点右侧的1的数量减少1,以补偿我们从0切换到1的位。

我们的新位模式将成为 111101011 - 十进制491(我们保留了未设置的位数,未按输入设置)

int getNextNumber(int input)
{
    int flipPosition=0;
    int trailingZeros=0;
    int trailingOnes=0;
    int copy = input;

    //count trailing zeros
    while(copy != 0 && (copy&1) == 0 )
    {
        ++trailingZeros;

        //test next bit
        copy = copy >> 1;
    }

    //count trailing ones
    while(copy != 0 && (copy&1) == 1 )
    {
        ++trailingOnes;

        //test next bit
        copy = copy >> 1;
    }

    //if we have no 1's we cannot form another patter with the same number of 1's
    //which will increment the input, or if we have leading consecutive
    //zero's followed by consecutive 1's up to the maximum bit size of a int
    //we cannot increase the input whilst preserving the no of 0's and
    //1's in the original bit pattern
    if(trailingZeros + trailingOnes  == 0 || trailingZeros + trailingOnes == 31)
        return -1;

    //flip first 0 followed by a 1 found from the right of the bit pattern
    flipPosition = trailingZeros + trailingOnes+1;
    input |= 1<<(trailingZeros+trailingOnes);

    //clear fields to the right of the flip position
    int mask = ~0 << (trailingZeros+trailingOnes);
    input &= mask;

    //insert a bit pattern to the right of the flop position that will contain
    //one less 1 to compensate for the bit we switched from 0 to 1
    int insert = flipPosition-1;
    input |= insert;

    return input;
}