publicstaticintlog2DeBruijn(int value){ value =isPowerOfTwo(value)? value :smallestEncompassingPowerOfTwo(value);returnMULTIPLY_DE_BRUIJN_BIT_POSITION[(int)((long)value *125613361L>>27)&31];}
publicstaticintsmallestEncompassingPowerOfTwo(int value){inti= value -1; i = i | i >>1; i = i | i >>2; i = i | i >>4; i = i | i >>8; i = i | i >>16;return i +1;}
从输入值的第一个1开始,到最右边的那一位,我们想把里面所有的0化成1,我们把输入值看成两部分,一部分是x,是x<=value的最大2的幂次,另外一部分为y,其中y=value-x,我们可以证明x>y,因为如果x<=y,那么y可以重新分为x,y-x两部分,那么value可以分为value=y-x+2x,如果x是2的幂次,那么2x也是2的幂次,这与x为x<=value内最大的2次幂矛盾,故不成立。我们设置不小于value的最小2的幂次为m,这里的x,就是输入值化为二进制后的1的最高值的十进制,那么根据y<x的特点,我们只需要修正1的最高值右边的位中的0为1,就不会导致value>m,这样就不会导致算出的m发生变化,所以我们只需要想办法把1的最高次右边的0改为1就可以。哪么如何改呢?我们知道:1 AND x = 1其中x为0或1,所以我们只需要拿一个1按位与上1的最高位右边的位数,但是这个1不能作为单独的1而存在,它得是8位的,这样的话对1的位置就有关系了,在刚开始时,我们应该拿应该在输入值的1的最高次位-1处为1的8进制数,这样的话我们不可能事先定义好,但是我们可以把输入的值右移1位就可以获得了。那有必要一位一位移吗,显然是没必要的,刚开始时,从左到右,第一位本来就是1,第二位在第一步后变成了1,所以你现在有两位1了,你完全可以把这两位1同时移到后面两位上,这样一次与操作就可以解决两位了,类似的,完成4位后就可以右移四位,然后得到了八位1,然后又可以移动8位...一直到移动16位,我们知道int型的变量是32位,16位的移动已经是极限了,如果移动32位,那就相当于没移动。这样我们就可以得到一个全1序列,而且这个序列的最高的1的位置不变,此时要想得到一个不小于输入值的二次幂,只需要加1就可以了,因为全是1,所以加的1会传导到最前面,1的最高次会往前(左)搬移一位,而后面(右边)的位数全是0,这样我们就得到了一个不小于输入值的最小2次幂,但还有一个问题,我们最后加了一个1,为了得到真正的值,我们应当在开头减去1,以达到平衡。