java位运算

java中的位运算,涉及到计算机二进制,位用bit表示,1 byte=8bit,根据各种基本数据类型占用的字节空间,可以计算各种数据有多少位二进制,可以算出对应的取值范围。

java中的位运算包括:(&)运算,(|)运算,异或(^)运算,(~)运算;以及移位运算:左移运算(<<),右移运算(>>),无符号右移运算(>>>),注意没有无符号左移运算。

1、与运算符&(and)

       与运算,两个数值进行与运算时,转换成二进制数据,两个数值中进行比对,位都为1,结果数值对应的位才为1,否则对应的位为0;

例如:5&6运算

十进制5对应的二进制为101

十进制6对应的二进制为110

运算结果为:100(二进制),则对应的十进制就是4;

2、或运算符 |(or)

      或运算,两个数值进行比对,只要有一个数值对应的位是1,则结果数值对应的位就为1,否则对应的位为0;

例如:5 | 6运算

十进制5对应的二进制为101

十进制6对应的二进制为110

与运算结果为:111(二进制),对应的十进制为7;

3、异或运算符 ^(xor)

     异或运算,两个数值进行比对,两个数值中,相同的位都为0或者都为1(即相同位值相同),则结果数值中对应的位则为0,不同,则结果数值中对应的位就为1;

例如:5 ^6运算

十进制5对应的二进制为101

十进制6对应的二进制为110

异或运算之后的结果为:011,对应的十进制为3;

注意:这里的^符号与我们平时用来做乘幂的^不同,java中不用^来做乘幂运算,java中做乘幂运算有数学函数Math.pow(x,a)来负责,表示x的a次方

4、非运算符 ~(not)

非运算是针对单个数值来运算,数值转换成二进制后,对应的位是0,则结果数值中对应的位是1,如果位是1,则对应的结果的位是0

例如:~5

十进制5对应的二进制为0000 0000 0000 0000 0000 0000 0000 0101

非运算后结果为:1111 1111 1111 1111 1111 1111 1111 1010 ,对应的十进制为-6


第二部分:移位运算

   运算符                                                         含义                  举例
     <<左移运算符,表示将二进制数据向左移动相应的位数(在低位处补上相应位数的0)             19<< 3
     >>右移运算符,区别于“无符号”右移运算符,将运算符左边的十进制数值转换为二进制,然后整体向右移动运算符右边指定数的位数,使用符号拓展机制,如果值是正,则在高位补上0,反之为负,则在高位补上1             19>>3
   >>>“无符号”右移运算符,将运算符左边的十进制数值转为二进制后运算,二进制数据整体右移指定的位数,采用0扩展机制无论值为正负,都在高位补0           19>>>3

1、 分析左移运算

十进制19对应的二进制为10011,左移3位,原本5位的二进制,变为8位,多出的三位在低位,补0,结果为10011000,十进制数值为152,左移运算相当于原来的数值乘以2的位移位数次幂,如本例结果为19*2*2*2=152;

2、 分析有符号右移运算

十进制19对应的二进制为10011,右移3位,原本5位的二进制,变为2位(低位3位被挤掉),高位补三位,补0,结果为00010,十进制数值为2

当十进制取值为负数时,例如取值-19,则结果不同-19对应的二进制为

{补充负数二进制的获取方法:首先用-19的相反数19取二进制为10011,19的二进制10011为原码(一个整数按照绝对值大小转换成的二进制数,是为原码。32位,前面是0省略掉了0000 0000 0000 0000 0000 0000 0001 0011),然后取反(0的变成1,1的变成0。),得到反码1111 1111 1111 1111 1111 1111 1110 1100,反码再加1为1111 1111 1111 1111 1111 1111 1110 1101得到的是补码,则-19表示为二进制就是1111 1111 1111 1111 1111 1111 1110 1101,-19右移3位,高位补1,二进制为1111 1111 1111 1111 1111 1111 1111 1101),对应十进制为-3;

 

3、分析无符号右移运算(int值占4字节,因为用的eclipse测试,是用的32位)

19>>>3,对应的十进制结果也是2

-19>>>3,-19对应的二进制为1111 1111 1111 1111 1111 1111 1110 1101,-19右移3位,高位补0,则为0001 1111 1111 1111 1111 1111 1111 1101,对应的十进制为536870909;

 

以下是在eclipse中测试的结果:

package review;

public class BitWise {
public static void main(String[] args) {
	
	System.out.println("5&6="+(5&6));
	System.out.println("5|6="+(5|6));
	System.out.println("5^6="+(5^6));
	System.out.println("19<<3="+(19<<3));
	System.out.println("19>>3="+(19>>3));
	System.out.println("-19>>3="+(-19>>3));
	System.out.println("19>>>3="+(19>>>3));
	System.out.println("-19>>>3="+(-19>>>3));

}
}

控制台输出的结果为:

 然后添加一下对应运算的二进制的输出形式,可以与上边的进行比照(现在习惯使用idea了,用idea补充 一下二进制输出形式)

    @Test
    public void testBitwiseOperation() {
        System.out.println("与运算 5&6 运算后的二进制形式:" + Integer.toBinaryString(5 & 6));
        System.out.println("或运算 5|6 运算后的二进制形式:" + Integer.toBinaryString(5 | 6));
        System.out.println("异或运算 5^6运算后的二进制形式:" + Integer.toBinaryString(5 ^ 6));
        System.out.println("左移运算 19<<3运算后的二进制形式:" + Integer.toBinaryString(19 << 3));
        System.out.println("右移运算 19>>3运算后的二进制形式:" + Integer.toBinaryString(19 >> 3));
        System.out.println("右移运算 -19>>3运算后的二进制形式:" + Integer.toBinaryString(-19 >> 3));
        System.out.println("无符号右移运算 19>>>3运算后的二进制形式:" + Integer.toBinaryString(19 >>> 3));
        System.out.println("无符号右移运算 -19>>>3运算后的二进制形式:" + Integer.toBinaryString(-19 >>> 3));

        System.out.println("非运算 ~5运算后的二进制形式:" + Integer.toBinaryString(~5));
        System.out.println("非运算 ~5运算后的十进制数字:" + (~5));

    }

输出结果:

最后补充一个位运算的算法题:(题目来自lintcode,答案来自九章算法)

题目:不使用加法运算符计算a+b

答案:

/**
* 本参考程序来自九章算法,由 @九章算法 提供。版权所有,转发请注明出处。
* - 九章算法致力于帮助更多中国人找到好的工作,教师团队均来自硅谷和国内的一线大公司在职工程师。
* - 现有的面试培训课程包括:九章算法班,系统设计班,算法强化班,Java入门与基础算法班,Android 项目实战班,
* - Big Data 项目实战班,算法面试高频题班, 动态规划专题班
* - 更多详情请见官方网站:http://www.jiuzhang.com/?source=code
*/ 

class Solution {
    /*
     * param a: The first integer
     * param b: The second integer
     * return: The sum of a and b
     */
    public int aplusb(int a, int b) {
        // 主要利用异或运算来完成 
        // 异或运算有一个别名叫做:不进位加法
        // 那么a ^ b就是a和b相加之后,该进位的地方不进位的结果
        // 然后下面考虑哪些地方要进位,自然是a和b里都是1的地方
        // a & b就是a和b里都是1的那些位置,a & b << 1 就是进位
        // 之后的结果。所以:a + b = (a ^ b) + (a & b << 1)
        // 令a' = a ^ b, b' = (a & b) << 1
        // 可以知道,这个过程是在模拟加法的运算过程,进位不可能
        // 一直持续,所以b最终会变为0。因此重复做上述操作就可以
        // 求得a + b的值。
        while (b != 0) {
            int _a = a ^ b;
            int _b = (a & b) << 1;
            a = _a;
            b = _b;
        }
        return a;
    }
};

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值