源码

public static int numberOfLeadingZeros(int i) {
// HD, Count leading 0's
if (i <= 0)
return i == 0 ? 32 : 0;
int n = 31;
if (i >= 1 << 16) { n -= 16; i >>>= 16; }
if (i >= 1 << 8) { n -= 8; i >>>= 8; }
if (i >= 1 << 4) { n -= 4; i >>>= 4; }
if (i >= 1 << 2) { n -= 2; i >>>= 2; }
return n - (i >>> 1);
}

摘自JDK11.0.6源码


功能解释

该方法调用返回传入值二进制表示最高位(包含符号位)前0的个数,如果传入值为负数则返回0。

####1.传入值为负数

任意一个负数的二进制表示为一定为:

1xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

最高位为1,前面有0个符号位,则返回0;

2.传入值为0

0的二进制表示为:

0000 0000 0000 0000 0000 0000 0000 0000

全为0,共32个,返回32;

3.传入值为正数

任取一个正数其二进制位数为:

01xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

最高位为1,x为任意值。

//执行到这里,i >= 1,则最多有31个0,初始化计数器。
int n = 31;
//判断 i 的最高位在低16位,高16位。如果在高16位,则0的个数小于16,计数器减去16,将高16位移动到低16位
if (i >= 1 << 16) { n -= 16; i >>>= 16; }
//执行完结果为 0000 0000 0000 0000 01xx xxxx xxxx xxxx 此时 n = 15
//判断 i 的最高位在低8位,高8位。如果在高8位,则0的个数小于24,计数器再减去8,将高8位移动到低8位
if (i >= 1 << 8) { n -= 8; i >>>= 8; }
//执行完结果为 0000 0000 0000 0000 0000 0000 01xx xxxx 此时 n = 7
//判断 i 的最高位在低4位,高4位。如果在高4位,则0的个数小于28,计数器再减去4,将高4位移动到低4位
if (i >= 1 << 4) { n -= 4; i >>>= 4; }
//执行完结果为 0000 0000 0000 0000 0000 0000 0000 01xx 此时 n = 3
//判断 i 的最高位在低2位,高2位。如果在高2位,则0的个数小于30,计数器再减去2,将高2位移动到低2位
if (i >= 1 << 2) { n -= 2; i >>>= 2; }
//执行完结果为 0000 0000 0000 0000 0000 0000 0000 0001 此时 n = 1
//判断 i 的最高位在第1位,还是第2位,如果是1,则i>>>1=0, 返回计数器,如果第2位,则i>>>1 = 1
return n - (i >>> 1);

思想

该方法采用的二分法的方法进行判断,如果在高位就将低位右移处理掉。如果在低位在进一步判断是在低位的高半,还是低半位中。