Integer之numberOfLeadingZeros

源码为

public static int numberOfLeadingZeros(int i) {
        // HD, Figure 5-6
        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的个数返回,
由于负数第一位符号位是1,所以必然返回0

     if (i >>> 16 == 0) { n += 16; i <<= 16; }

i >>> 16,这表示i向右移动16位,与i>>16不同
'>>右移时如果是正数会补0,负数会补1,而>>>只会补0,举例

8>>2  =  0100 -> 0001
8>>>2 = 0100 -> 0001
-8>>2 = 1100 -> 1111  //实际上负数是以补码形式保存,这里只是举例
-8>>>2 = 1100 -> 0011  // 高位补0

在看源码

i >>> 16 == 0
// 00000000 00000000 00000000 00000000 

实际上表示的是前16位为0,

 i <<= 16

表示将i左移16位后再赋值给i,整句的意思是如果i前16位为0,则把后16位移动到前16位,并给后16位补0。
通俗点讲就是,先判断前面16位是不是0,如果是0就把前16位去掉,后面的顶上。
后续的

if (i >>> 24 == 0) { n +=  8; i <<=  8; }

i>>>24实际上判断的是8位,之后再判断前4位,再判断前2位

        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;

n就是统计0的数量,但是我们注意到n的初始值为1,按理说不应该是0吗?
原因在最后一句,如果i>>>31即i的末位是0的话,n应该要再加上1,但是这里实际上是减去了末位的值0,即少加了1,而如果末位的值是1本应该跳过,但这里却多减了1,所以n的初始值不是0而是1.

n -= i >>> 31;
也可以看做
if (i >>> 31 == 1) { n -=  1;  }

至于作者为什么要这样写,不得而知,如果你有什么看法欢迎留言讨论~
如果把n的初始值设为0,这个方法也可以这么写

public static int numberOfLeadingZeros(int i) {
        // HD, Figure 5-6
        if (i == 0)
            return 32;
        int n = 0;
        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; }
        if (i >>> 31 == 0) { n += 1;};
        return n;
    }

这种二分判断法方法让原来需要比较32次减少至比较5次,大大提高了效率
它还有一个姐妹方法,统计从右边开始的0个数,类似就不再叙述了

public static int numberOfTrailingZeros(int i) {
        // HD, Figure 5-14
        int y;
        if (i == 0) return 32;
        int n = 31;
        y = i <<16; if (y != 0) { n = n -16; i = y; }
        y = i << 8; if (y != 0) { n = n - 8; i = y; }
        y = i << 4; if (y != 0) { n = n - 4; i = y; }
        y = i << 2; if (y != 0) { n = n - 2; i = y; }
        return n - ((i << 1) >>> 31);
    }

你可能感兴趣的:(Integer之numberOfLeadingZeros)