我正在研究一个问题,我给出了一个数字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);
}
但我想了解它将始终有效的算法的基本逻辑。所有边界案件都将得到妥善处理。
有人可以通过简单的步骤解释逻辑。
由于
答案 0 :(得分:1)
在下一个较高的数字中,最右侧1
个交换的最左侧1
位于其左侧的0
,而剩余的1
移动到最右边。
1
,a
(使得携带波动到下一个更高的0
,反转所有这些位)0
的地方),1
为0
的右端提供了更多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;
}