Integer.numberOfLeadingZeros()源码原理,该如何处理

Integer.numberOfLeadingZeros()源码原理
	
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;
}

该函数可以返回二进制首部开始0的个数
如:2818048,对应二进制:00000000  00101011  00000000  00000000,会返回10

但是这个函数的原理是什么呢?而且为什么基准选定的分别是2的1、2、3、4次幂呢?
------解决思路----------------------
引用:
Quote: 引用:

这里典型的二分查找思路。

if (i >>> 16 == 0) { n += 16; i <<= 16; }  先看左边的16位,如果有,记16个,如果没有,把右16位移到左边。 

然后依次是8位,4位,2位,1位,依次类推。
大哥您好,问个挺弱的问题,,,这里为什么就能选中16、8、4、2、1,怎么就不选9、7、5、3、1呢......,是根据什么思路二分查找的...或者我该去补一下什么叫二分查找?


这。。。问题问的就像为何INT在32位系统上用四个byte一样。。。。

我实在无法回答 。。。
------解决思路----------------------
引用:
Quote: 引用:

这里典型的二分查找思路。

if (i >>> 16 == 0) { n += 16; i <<= 16; }  先看左边的16位,如果有,记16个,如果没有,把右16位移到左边。 

然后依次是8位,4位,2位,1位,依次类推。
大哥您好,问个挺弱的问题,,,这里为什么就能选中16、8、4、2、1,怎么就不选9、7、5、3、1呢......,是根据什么思路二分查找的...或者我该去补一下什么叫二分查找?


首先,查找从首部开始0的个数,可以理解成查找从首部开始第一个1的位置。针对这个问题numberOfLeadingZeros方法用了二分查找法。至于为什么二分查找的中值要选16->8->4->2->1,个人认为这样取值的的平均比较次数最少,不管要找的元素位于哪个位置,每次比较都能淘汰集合中一半的元素,从而能够快速定位。
------解决思路----------------------
看看这样解释是否清楚一些:

// 首先在jvm中一个int类型的数据占4个字节,共32位,其实就相当于一个长度为32的数组。
// 那我们要计算首部0的个数,就是从左边第一个位开始累加0的个数,直到遇到一个非零值。
public static int numberOfLeadingZeros(int i) {
if (i == 0)                                                                       
             return 32;
int n = 1;
// 下面的代码就是定位从左边开始第一个非零值的位置,在定位过程中顺便累加从左边开始0的个数
// 将i无符号右移16位后,有二种情况;
//   情况1.i=0,则第一个非零值位于低16位,i至少有16个0,同时将i左移16位(把低16位移到原高16位的位置,这样情况1和情况2就能统一后续的判断方式)
//   情况2.i!=0,则第一个非零值位于高16位,后续在高16位中继续判断
// 这个思路就是二分查找,首先把32位的数分为高低16位,如果非零值位于高16位,后续再将高16位继续二分为高低8位,一直二分到集合中只有1个元素
if (i >>> 16 == 0) { n += 16; i <<= 16; }
// 判断第一个非零值是否位于高8位
if (i >>> 24 == 0) { n +=  8; i <<=  8; }  
// 判断第一个非零值是否位于高4位
if (i >>> 28 == 0) { n +=  4; i <<=  4; }
// 判断第一个非零值是否位于高2位
if (i >>> 30 == 0) { n +=  2; i <<=  2; }       
// 判断第一个非零值是否位于左边第一位
n -= i >>> 31;                                                                
return n;
}