n不是2的m次方,要求下一个符合2的m次方的数
这个算法很多地方都有了 只是没详解 小的愚昧 整理于此 做个备忘 对你有用更好 没有勿喷
下面是我请教别人的地方,或许他们的解释更容易让你明白
http://topic.csdn.net/u/20110926/09/8ac6fb0f-d59a-4506-8536-c6d1bbb4ea79.html
public static int test(int n){
n -= 1;
n |= n >>> 1;
System.out.println(n);
n |= n >>> 2;
System.out.println(n);
n |= n >>> 4;
System.out.println(n);
n |= n >>> 8;
System.out.println(n);
n |= n >>> 16;
System.out.println(n);
return n + 1;
}
n之所以要减一是为了满足n本身就是2的m次幂这种情况
最高位1扩充到后面的所有位,然后再加一
2的m次幂跟2的m次幂-1的关系是这个算法的关键。比如100 跟111相差一,从另一个角度来看,我可以看成100是111加一求得100的
101的下一个符合2的m次幂的数是100,即四,我们可以这么来做,将最高位1扩充到后面的所有位。
首先将n向右逻辑右移一位(以后说的移位都为逻辑移位),然后再与n求或操作,保存为n,这样保证最高位和右边第一位为1,
接下来都是重复这个动作,但是如何高效的覆盖右边所有位,使之为1呢?
第一次移位然后求或,我们已经获得了最高位和次高位两位为1,那么我们再在第一步的基础上右移两位,然后与第一次得到的最终结果求或,
是不是最高四位都为1了?
现在我们已经获得了最高4位全为1,第三次右移我们可以一次移4位,移完求或后我们可以获得最高8位都为1了。
第四次我们一次移八位,然后求或,可以得到最高16位都为1。
第五次,我们再移16位,现在最高位以下所有的位都为1了,形如11...111的形式
最后,在这个值上加一就求得了n的下一个符合2的m次幂的数
写到这里,我发现完全不用这么麻烦了,首先判断这个数是不是2的m次幂
n & (n-1) == 0
如果等于零则说明他满足条件,返回
不等于零,则将该数左移一位,将最高位以后的所有位清零不就得到了哦