Integer类中的numberOfLeadingZeros(i
源码:
public static int numberOfLeadingZeros(int i) {
//
if (i == 0) //步骤一
return 32;
int n = 1;
//步骤二
if (i >>> 16 == 0) { n += 16; i <<= 16; }//分析一
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
n -= i >>> 31;//分析二
return n;
}
方法功能
该方法的作用是返回无符号整型i的最高非零位前面的0的个数,包括符号位在内;
如果i为负数,这个方法将会返回0,符号位为1.
比如说,10的二进制表示为 0000 0000 0000 0000 0000 0000 0000 1010
java的整型长度为32位。那么这个方法返回的就是28
分析
1.这一系列的判断,实际上是二分法的应用。
这里有一个比较巧妙的实现就是如果判断成立,那么成立之后会对i进行移位操作。
实际上就是因为条件成立,所以非零位在低16位,为方便后面处理(后面都是判断的高16位),将低16位左移到高16位位置。
2.分析二的位置实际上就是二分法对最后两个数的判断。n初始化为1,因此,如果判断最后的位为1,那么就减少一个n的数,否则为i>>>31为0的话,那么就不操作(n原先有一个1)
方法的实现分为下面几个步骤
1.判断整型i的值是否为0,如果是,那么表明0的个数为32个,直接返回即可
2.判断i无符号右移16位后的值是否为0.判断的是高16位的第一个非0数字是否存在。
条件成立,则表明第一个非0位在低16位
否则,第一个非零值在高16位。
3.如果前面的判断条件成立,(i>>>16 == 0) 那么进入if里面的语句之后,会将i向左移,将低16位变成高16位,对低16位进行计数。
如果判断不成立,即使非零位在高16为那么就没有必要进行移位的处理
4.后面的判断与第一个类似。
实例
比如一个数:0100 0010 0000 0010 0000 000
右移16位后
右移16位
结果为:
原先的高16位.png
因此,对于该数,判断条件 i>>>16==0 不成立,条件成立表明第一个非零数位于高16位。
此时的n=1
- 进入下一个if判断语句:
if (i >>> 24 == 0)
右移后判断.png
得到一个全0的数,条件成立,进入if结构块,n=9
然后i进行左移8位的操作,把0100 0010 移动到最高位,此时
i = 0100 0010 0000 0010 0000 0000 0000 0000
- 然后进入下一个判断,i>>>28 ==》得到 0000 0000 0000 000 0000 0000 0000 0100
不为零 - 进入下一个 i>>>30 ==》 0000 0000 0000 0000 0000 0000 0000 0001
不为零. - 执行最后一条语句i>>>31,此时该句结果为0,因此最终的结果n为9.
与实际情况相符。
其他
该方法实际上是一种二分法,不断的从中间的位置向左计算0的个数。如果左边都为0,那么就把右边的数移动左边,以此计算右边零的个数。
这个方法的实现可读性有点差。