Integer.bitCount()理解

环境说明

注意:Java使用补码来表示整数并参与运算。

环境:JDK1.8

 

源码解析

/**
 * 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>.
 * 返回指定值的二进制补码表示形式中1的个数。
 *
 * @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
 */
public static int bitCount(int i) {
    // HD, Figure 5-2
    i = i - ((i >>> 1) & 0x55555555); //计算两位中1的个数
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);//计算四位中1的个数
    i = (i + (i >>> 4)) & 0x0f0f0f0f;//计算八位中1的数
    i = i + (i >>> 8);//计算十六位中1的个数
    i = i + (i >>> 16);//计算三十二位中1的个数
    return i & 0x3f;//0x3f的二进制{24个0}00111111,表示2^6-1=63。而int的最大长度是32位,所以1的个数最大为32,所以取低6位就够了。
}

 

主要思路

思路说明

bitcount的思想,与二路归并排序是类似的。

主要运用了“分治算法”,分治算法就是将一个大的问题划分为n个规模较小而结构相似的子问题。

这些子问题解决的方法都是类似的,解决掉这些小的问题之后,归并子问题的结果,就得到了“大”问题的解。

 

 

计算bitCount的思想总体上分两个阶段【依次:每4位、每8位、每16位、每32位】:

1、计算每两位中1的数量,将原来表示数值的二进制数变成每两位表示这两位中“1”数量的二进制数。

2、将这些数量加在一起。

 

源码中用到的十六进制和二进制的关系说明

行数十六进制二进制说明
第一行0x5555555501010101010101010101010101010101计算两位中的1个数
第二行0x3333333300110011001100110011001100110011计算四位中的1个数
第三行0x0f0f0f0f00001111000011110000111100001111计算八位中的1个数
第四行、第五行  只需要关注二进制的后六位就可以了,因为32位int值不可能超过2^6-1(63)个“1”
第六行  最后在return语句中将第四行、第五行代码的垃圾数据过滤掉只保留最后6位,还是为了效率。

 

大家参考上面,可以自己分析一下Long的bitcount。

/**
 * Returns the number of one-bits in the two's complement binary
 * representation of the specified {@code long} value.  This function is
 * sometimes referred to as the <i>population count</i>.
 * 返回指定值的二进制补码表示形式中1的个数。
 *
 * @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 long} value.
 * @since 1.5
 */
 public static int bitCount(long i) {
    // HD, Figure 5-14
    i = i - ((i >>> 1) & 0x5555555555555555L);
    i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
    i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    i = i + (i >>> 32);
    return (int)i & 0x7f;
 }

 

参考资料:
JDK源码
备注:
转载请注明出处:https://blog.csdn.net/WSYW126/article/details/105591500
作者:WSYW126

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值