Integer.bitCount和hightestOneBit的分析

Integer类有两个很有趣的方法,highestOneBit(int)和bitCount(int),前者是我指定HashMap初始化大小时寻找大于某个数的最小2的指数幂时候发现的,后者是看到leetcode上面一道算法题的时候,自己在Integer类中找到的解。下面上代码和分析过程。

(一)这是寻找最高位,我们使用 hightestOneBit(i) << 1就可以得到大于 i 的最小2的指数幂.

    public static int highestOneBit(int i) {
        // HD, Figure 3-1
        i |= (i >>  1);
        i |= (i >>  2);
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);
        return i - (i >>> 1);
    }

我们以196作为寻找最高位的数,来一步步看过程。196只留最高位之后剩下的是2的7次方。


①当我们执行完方法的第一次运算之后,最高位的后一位必定是1,这样最高位与其下一位都是1.


②而执行完第二次运算之后,最高位及其后三位都是1


③这样执行完右移4、8、16位与之后,最高位之后的所有位都是1,再与自身右移相减就只保留最高位了。


(二)bitCount(i)是用来统计二进制数中1的个数,这也是leetcode上面的一道题。

    public static int bitCount(int i) {
        // HD, Figure 5-2
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }

我们这次以1995作为参考来看整个运算过程

①第一次运算,0x55555555是一个很特殊的数,他的奇数位全是1,偶数位全是0,第一次运算就是每两位记录下1的个数


因为除了第一次运算,后面的运算都是加,如果第一次运算改成加也是一样的结果。


②0x33333333也是一个比较特殊的数,他是每4位数的前两位是0,后两位是1,第二次运算就是统计每4为中1的个数


③这样子后面的

i = (i + (i >>> 4)) & 0x0f0f0f0f;

i = i + (i >>> 8);

i = i + (i >>> 16);

都很容易理解了,就是统计每8位、16位、32位中1的个数,最后得到的数和63相与(因为int中1的个数不可能超过32,所以&63是取余),最后结果是8.

总结:Integer.hightestOneBit就是通过把最高位的1覆盖到后面的每一位,然后自身右移1位做差来保留最高位实现的。Integer.bitCount是通过计算每2位中1的个数、每4位中1的个数、每8位中1的个数、每16位中1的个数、每32位中1的个数来统计整个Integer中1的个数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值