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 前两位后再相加:( 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