当前位置: 代码迷 >> 综合 >> Integer.numberOfLeadingZeros
  详细解决方案

Integer.numberOfLeadingZeros

热度:34   发布时间:2024-02-07 11:57:19.0

计算一个int类型的数需要在左侧补充零的个数 中JDK(1.8)的实现

1 首先看这个方法有什么作用

下面這段是ConcurrencyHashMap中的一段逻辑

看下面注释

  • 1 和2 是我个人的理解待确认,但是第三个的意思比较明确,即每个对象指针占用的偏移的值应该是2的整数次幂 2^n

     pointer.offset.intValue = 2^n

  • int类型长度32位,符号占用1位,那么31 减去 需要补scale需要补零的个数,就是指针占用长度对应的2的整数次幂n

      即 31 减去 pointer.offset.intValue 需要在左侧补 0 的个数即为 n

Class<?> ak = Node[].class;ABASE = U.arrayBaseOffset(ak);
//  1 计算每个对象指针占用的地址的偏移
int scale = U.arrayIndexScale(ak);
// 2 scal 需要是2的整数次幂 
if ((scale & (scale - 1)) != 0)throw new Error("data type scale not a power of two");
// 3 计算出每个对象指针占用的位数(bit)
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);

 

2 接下来分析一下JDK的实现

public static int numberOfLeadingZeros(int i) {// HD, Figure 5-6if (i == 0)return 32;// 设置一个初始值,因为int类型有31位,二分法无法判断最后一位是0 还是 1 ,所以先假设最后一位        是1,其实此处完全可以优化一下即设置n=0,如果 i = 1 那么直接返回30即可。int n = 1; // 二分法,判断前16位,如果前16位为0 把低16位移动到高的16位,否则i值不变,继续判断对高的16位进行二分法判断// 如果高16位全部为0 则低16位被动到高16位,即此处既可能为低16位,也可能为高16位if (i >>> 16 == 0) { n += 16; i <<= 16; }// 通上,此处既可能为高8位也可能为低8位if (i >>> 24 == 0) { n +=  8; i <<=  8; }// 判断前// 通上,此处既可能为高2位也可能为低2位
if (i >>> 28 == 0) { n +=  4; i <<=  4; }// 完成判断,因为int类型32位。符号占1位。int 类型占31位 二分法无法判断 最后一位,所需要判断最后一位是1 还是 0if (i >>> 30 == 0) { n +=  2; i <<=  2; }n -= i >>> 31;return n;
}

3 注意

位右移  >>> 和 >> 的区别,前者不带符号位移,后者位移时会连同符号一起移动,  

  相关解决方案