Java源码分析:Integer中的位运算

 

Integer中用到了很多位运算,而java整数的固定长度也为位运算提供不少便利性,下面对Integer中的经典方法做分析(这些方法基本上都用到了位运算,原因很简单:高效,并行)

 

 

1.求整数中二进制1的个数

public static intbitCount(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);

returni & 0x3f;

}

分析:该方法仅需五步完成,时间复杂度是O(logN)(N是整数的二进制长度),算法妙在二进制并行运算,之后的算法很多也用到了并行运算。

分解:

第一步:求每两位中1的个数之和,比如i=(01)( 11)( 00)( 10)( 11)( 01)( 11)(01)->(01)(10)(00)(01)(10)(01)(10)(01)

第二步:求前面结果的每四位之和    (0110)(0001)(1001)(1001)->(0010)(0001)(0010)(0010)

第三步:同上道理,求每8位置和

。。。。

 

并行:比如求没两位之和时,不用先等前面两位算完再算后面两位,直接同时进行,这也是位运算一大特色

 

2.返回具有至多单个1 位的 int 值,在指定的 int 值中最高位(最左边)的 1 位的位置

public static inthighestOneBit(int i) {

        // HD, Figure 3-1

        i |= (i >>  1);

        i |= (i >>  2);

        i |= (i >>  4);

        i |= (i >>  8);

        i |= (i >> 16);

        return i - (i >>> 1);

}

 

分析:该方法时间复杂度是O(logN)

分解:

第一步:让整数二进制最高位为1的右边一位也为1

第二步:让整数二进制最高位为1的右边3位也为1

第三步:让整数二进制最高位为1的右边7位也为1

。。。。

最后整数二进制最高位为1的右边全为1,然后通过运算只保留最高位的1

 

3.返回具有至多单个 1 位的 int 值,在指定的 int 值中最低位(最右边)的 1位的位置

public static intlowestOneBit(int i) {

        // HD, Section 2-1

        return i & -i;

 }

分析:该方法一步完成,妙哉!

 

4.在指定 int 值的二进制补码表示形式中最高位(最左边)的 1 位之前,返回零位的数量

public static intnumberOfLeadingZeros(int i) {

        // HD, Figure 5-6

        if (i == 0)

            return 32;

        int n = 1;

        if (i >>> 16 == 0) { n += 16;i <<= 16; }

        if (i >>> 24 == 0) { n +=  8; i <<=  8; }

        if (i >>> 28 == 0) { n +=  4; i <<=  4; }

        if (i >>> 30 == 0) { n +=  2; i <<=  2; }

        n -= i >>> 31;

        return n;

    }

分析:时间复杂度是O(logN),采用了类似二分查找的思想

 

5.返回指定的 int 值的二进制补码表示形式中最低(“最右”)的为 1 的位后面的零位个数

public static intnumberOfTrailingZeros(int i) {

        // HD, Figure 5-14

inty;

if(i == 0) return 32;

intn = 31;

y= i <<16; if (y != 0) { n = n -16; i = y; }

y= i << 8; if (y != 0) { n = n - 8; i = y; }

y= i << 4; if (y != 0) { n = n - 4; i = y; }

y= i << 2; if (y != 0) { n = n - 2; i = y; }

returnn - ((i << 1) >>> 31);

    }

分析:类似上一方法

 

6.反转二进制整数

public static intreverse(int i) {

        // HD, Figure 7-1

i= (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;

i= (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;

i= (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;

i= (i << 24) | ((i & 0xff00) << 8) |

    ((i >>> 8) & 0xff00) | (i>>> 24);

returni;

    }

分析:时间复杂度是O(logN),采用分治法,先局部后整体

分解:第一步:每相邻两位互换

第二步:每相邻四位互换,四位内部不互换

…..

 

7.获得整数征服符号表示:10-1

public static intsignum(int i) {

        // HD, Section 2-7

        return (i >> 31) | (-i>>> 31);

}

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值