zoukankan      html  css  js  c++  java
  • Java源码解释之Integer.bitCount

    Java中的Integer.bitCount(i)的返回值是i的二进制表示中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;
    }
    

    源码解析如下:

    public static int bitCount(int i) {
            // HD, Figure 5-2
            /**
             * 每两位为一个单元,把原来单元中1的个数储存在原来的单元中
             */
            i = i - ((i >>> 1) & 0x55555555);
            /**
             *0x33333333其实就是二进制……00110011(共32位),因为上面的每两位代表1的个数,所以下面的这几行就是要把上面每两位
             * 的数字加起来,下面的这行代码可以这样理解,每4位分为一组,然后4位中的每两位相加,相加的结果在储存到这4位二进制数中,
             * i & 0x33333333表示每4位中的低2位,(i >>> 2) & 0x33333333表示每4位中的高2位,然后在相加
             */
            i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
            /**
             * 这个更好理解,i >>> 4表示往右移动了4位,然后在与i相加,相当于每8位一组,然后8位中的高4位与低4位相加储存在低4位中,
             * 然后这里在与0x0f0f0f0f进行与运算,把高4位完全置为0了,因为0x0f0f0f0f用二进制表示就是00001111000011110000111100001111,
             * 看到这里可能有些困惑,这里为什么要与0x0f0f0f0f进行与运算,因为每8位一组的话,最多也就是8,那么4位数足够了,高4位就没有必要了,
             * 如果不置为0有没有影响,其实如果1的位数极少的话是没什么影响的,但如果1的位数比较多到后面计算的结果可能就会往前进位,导致结果错误,
             * 所以这一步要进行一次与运算,那为什么上面的那行代码没有把4位一组中的高两位置0,这是因为4位一组最多有4个1,而2位二进制数最多表示3,
             * 小于4,所以不能置为0,
             *
             */
            i = (i + (i >>> 4)) & 0x0f0f0f0f;
            /**
             * 和上面类似,每16位分为一组,每组中的高8位和低8位相加,这里的代码相加的很干净,因为无论是高8位还是低8位中的前4位在上面一行中
             * 都已经置为0了,这里也可以像上面那样,加完之后在与0x00ff00ff进行与运算,但其实这里已经没有必要了,因为int类型为32位,
             * 最多也就32个1,用8位数储存足够了,所以不会超过8位,也就不用担心超过8位在往前进1位的问题了。
             */
            i = i + (i >>> 8);
            /**
             * 和上面类似,就不在详述
             */
            i = i + (i >>> 16);
            /**
             * 到最后为什么要和0x3f进行与运算,0x3f用二进制表示就是111111,因为上面两行没有进行与运算,所以前面的数据都是无效的,
             * 只有最后8位是有效的,而后8位的前两位不用说肯定为0,因为最多也就32个1,用后面6位数表示就已经足够了,所以这里与0x3f
             * 进行与运算,来计算出最终1的个数
             */
            return i & 0x3f;
    }
    

    i=031bi

  • 相关阅读:
    转!!javaMail使用网易163邮箱报535 Error: authentication failed
    银行卡验证(验证是否存在,卡号类型,归属行)
    Navicat已经成功连接,密码忘记的解决方法
    Inline&IAT Hook原理
    x64dbg尝鲜
    C# 通过Dynamic访问System.Text.Json对象
    dotnet5将asp.net webapi宿主到wpf
    Asp.Net5 MVC with Vue.js
    在 Visual Studio 中使用跟踪点将信息记录到“输出”窗口中
    WPF带阴影的无边框窗体
  • 原文地址:https://www.cnblogs.com/inmoonlight/p/9301733.html
Copyright © 2011-2022 走看看