Java源码 Integer.bitCount原理

  @HotSpotIntrinsicCandidate
    public static int bitCount(int i) {
        i -= i >>> 1 & 1431655765;
        i = (i & 858993459) + (i >>> 2 & 858993459);
        i = i + (i >>> 4) & 252645135;
        i += i >>> 8;
        i += i >>> 16;
        return i & 63;
    }

符号说明:

>>> = 无符号右移

1431655765 = 0x55555555 = 二进制 0101 0101 0101 0101 0101 0101 0101 0101

  858993459 = 0x33333333 = 二进制 0011 0011 0011 0011 0011 0011 0011 0011

  252645135 =  0x0F0F0F0F = 二进制 0000 1111 0000 1111 0000 1111 0000 1111

 

思路:

  分组统计,两位两位一组来数

 

  有如下四种情况:

  • 数 -> 1的个数
  • 00 -> 00
  • 01 -> 01
  • 10 -> 01
  • 11 -> 10

  

  由于:    

  • 00 = 00 - 00;
  • 01 = 01 - 00;
  • 01 = 10 - 01;
  • 10 = 11 - 01;

  

  故 个数 = i - (i>>>1) 

 

第一步:

  当不止两位时,移位后高位可能从上一组移来一个1,需去除,于是 & 01 去除

  个数 = i - (i>>>1 & 0x55555555)

 

第二步:

  四位四位一组,两组两位两位的结果加起来,将前两位与后两位相加

    将前两位移到后两位:(i>>>2 & 0x33333333)

    清除 前两位后再相加:( i & 0x33333333) + (i>>>2 & 0x33333333)

 

第三步:

  同理8位整合两组4位,这里&优先级低于+,所以其实是 ( i + i>>>4) & 0x0F0F0F0F

 

第四步:

  同理16位整合两组8位

 

参考[1]: 

由于二等分是8位,而8位一共有4份。
A B C D

(C>>>8) + D D处8位的结果最大为 0001 0000不会进位到C。
(B>>>8) + C C处8位的结果最大为 0001 0000不会进位到B。
(A>>>8) + B B处8位的结果最大为 0001 0000不会进位到B。
A + 0 A处最大结果为 0000 1000

得到
A A+B B+C C+D
最后是求32位全部的内容也就是求(A+B)+(C+D)
A A+B B+C C+D
+
0 0 A A+B

也就是
λλ= i + (i >>> 16)
A A+B A+B+C A+B+C+D
A+B+C+D最大也就32个:
0000 0000 0000 0000 0000 0000 0010 0000
0000 0000 0000 0000 0000 0000 0011 1111 = 0x3F
之所以要return i&0x3F,就是把前面抹干净。

 

 

 参考:

[1] https://blog.csdn.net/cor_twi/article/details/53720640

[2] https://blog.csdn.net/qq_33977728/article/details/80252241

posted @ 2020-08-22 18:27  Numerz  阅读(266)  评论(0编辑  收藏  举报