前言
bitCount 源码采用自底向上的分治思想,通过找到数字规律,来完成分治。
一、源码解析
1、源码
/**
* Returns the number of one-bits in the two's complement binary
* representation of the specified {@code int} value. This function is
* sometimes referred to as the <i>population count</i>.
*
* @param i the value whose bits are to be counted
* @return the number of one-bits in the two's complement binary
* representation of the specified {@code int} value.
* @since 1.5
*/
@HotSpotIntrinsicCandidate
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;
}
2、核心所在
1)每两位统计1的个数、每四位统计1的个数、每八位统计1的个数…
2)将统计好的1放在每几位的低位上。
关键问题:
1- 两两分组得到1的个数?
通过将 i 拆解成多项式,然后对其做一定操作,得到每两位相加放在低位上。
- i >>> 1 后,
i = b1*2^0 + b2*2^1 + ... + b31*2^30
- (i >>> 1) & 0x55555555 后,
i = b1*2^0 + b2*2^1 + ... + b31*2^30
- (b2*2^1 + b4*2^3 + ... + b30*2^29)
- i - ((i >>> 1) & 0x55555555) 后,
i = b0*2^0 + b1*2^1 + ... + b31*2^31
- (b1*2^0 + b2*2^1 + ... + b31*2^30
- b2*2^1 + b4*2^3 + ... + b30*2^29)
= b0*2^0 + b1*2^1 + ... + b31*2^31
- (b1*2^0 + b3*2^2 + ... + b29*2^28 + b31*2^30)
= b0*2^0 + b1*(2^1-2^0) + ... + b31*(2^31-2^30)
= (b0+b1)*2^0 + (b2+b3)*2^2 + ... + (b30+b31)*2^30
2- 四四分组得到1的个数
- 运算前, 原始的i已被两两位一组的分为16组, 每组表示这两位中二进制1的个数
i = (b0+b1)*2^0 + (b2+b3)*2^2 + ... + (b30+b31)*2^30
- 运算后, 原始的i被四四位一组的分为8组,每组表示这四位中二进制1的个数
i = (b0+b1+b2+b3)*2^0 + (b4+b5+b6+b7)*2^4 + ... +(b28+b29+b30+b31)*2^28
3- 八八分组
- 运算后, i继续被八八位一组的分成4组, 每组表示这八位中二进制1的个数, 并且这八位中的前四位为0,, 因为4位二进制足够表示出每组中最大的数字8
i = (b0+b1+b2+b3+b4+b5+b6+b7)*2^0
+ (b8+b9+b10+b11+b12+b13+b14+b15)*2^8
+ (b16+b17+b18+b19+b20+b21+b22+b23)*2^16
+ (b24+b25+b26+b27+b28+b29+b30+b31)*2^24
4- 十六十六分组
- 运算后, i继续被分成4组, 但只有第一组和第三组是有效数据(每组表示这十六位中二进制1的个数), 其他组为垃圾数据
i = (b0+b1+b2+b3+b4+b5+b6+b7+b8+b9+b10+b11+b12+b13+b14+b15)*2^0
+ (b8+b9+b10+b11+b12+b13+b14+b15+b16+b17+b18+b19+b20+b21+b22+b23)*2^8
+ (b16+b17+b18+b19+b20+b21+b22+b23+b24+b25+b26+b27+b28+b29+b30+b31)*2^16
+ (b24+b25+b26+b27+b28+b29+b30+b31)*2^24
5- 三十二位
- 运算后, i继续被分成4组, 但只有第一组是有效数据(表示这32位中二进制1的个数), 其他组为垃圾数据
i = (b0+b1+...+b31)*2^0
+ (b8+b9+...+b30+b31)*2^8
+ (b16+b17+...+b30+b31)*2^16
+ (b24+b25+b26+b27+b28+b29+b30+b31)*2^24
6- 得到结果
- 运算后, 将上一步中第一组的有效数据提取了出来, 因为与上0x3f时大于2^5的数据都被置0, 而6位二进制足够表示32位int中的最大bitCount, 即32
i = (b0+b1+...+b31)*2^0 & 0x00111111
= (b0+b1+...+b31)*2^0
= b0+b1+...+b31
参考文献
[1] JDK 11
[2]
bitCount 源码解析
版权声明:本文为qq_43164662原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。