Integer.bitCount()解析

方法说明

把int类型转换成二进制,计算二进制中位==1的个数。当用位来存储状态时,方法比较有用

源码

   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;
    }

代码非常简单,但理解起来不那么简单,下面听我娓娓道来

  1. 方法的思想非常简单,我要计算32位中有多少个1,我先做切分,两个一组,总共分成16组,计算每个两位中有几个1,然后把16组加起来,不就得到总的1的个数了吗?
  2. 先看下两位时怎么计算1的个数

找规律

两位   个数
-----------------------
00       0
01       1
10       1
11       2

发现规律:如果高位是0,则结果和数值本身相同;如果是高位是1,则数值本身-1得到结果

  1. 于是我们得到公式 结果 = 参数 - (参数 >>1 & 01),满足上面规律
    这也是上面算法的第一行 i = i - ((i >>> 1) & 0x55555555);这样把数值分成了两两一组,并且每组中的数值即是1的个数

  2. 下面把所有组的数值加在一起就可以了,我们又两两加在一起。我们把高两位的右移两位和低两位加载一起就即可
    结果 =( 高两位 >>2 ) & 00 11 + 低两位 & 0011 , 之所以 & 0011 ,是为了防止高位污染结果
    即第二行代码 i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);

  3. 现在数值被4个一组分成了8组,想办法把这8个数值加在一起就OK了

  4. 还是一贯思想,再做聚合,8个一组,即是高4位右移4位和低位相加即可,别忘了把高4位搞掉
    i = (i + (i >>> 4)) & 0x0f0f0f0f;

  5. 接下来再做聚合,16个一组,高位右移8位+低位,现在为啥不搞掉高位了?我们先记住,这个数值中的高位是无效的

  6. 接下来16位一组分成2组,同理高16位也是无效

  7. 我们之道int类型位==1的最大个数是32位,即是 0000 0000 0000 0000 0000 0000 0010 0000,所以我们最后
    & 11 11111 即可,最大数值才是6位,所以第7\8步超过8位的数组就不用管了,最后会统一搞掉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章