Java位运算学习 左移位 右移位

Java中的位操作符有:

&:按位与。

|:按位或。

~:按位非。

^:按位异或。

<<:左移位运算符。

>>:右移位运算符。

<<<:无符号右移运算符。

与或非异或比较简单。

        //按位与( & )
        System.out.println(5 & 7);//输出为5
        System.out.println(5 & 3);// 结果为1
        System.out.println(4 & 1);// 结果为0

        // 按位或( | )
        System.out.println(5 | 3);// 结果为7

        // 按位异或( ^ )  
        System.out.println(5 ^ 3);//结果为6   

        // 按位非( ~ )   
        System.out.println(~5);// 结果为-6  


左移位运算符(<<):

将十进制数字转换为二进制后,整段数字向左移动,高位溢出的需要截断,低位补0。

比如2<<2,即2左移两位


//5左移两位
// 0000 0000 0000 0000 0000 0000 0000 0101 然后左移2位后,低位补0://
// 0000 0000 0000 0000 0000 0000 0001 0100 换算成10进制为20
//相当于5* 2的2次方
System.out.println(5 << 2);

//5左移三位
// 0000 0000 0000 0000 0000 0000 0000 0101 然后左移3位后,低位补0://
// 0000 0000 0000 0000 0000 0000 0010 1000 换算成10进制为40
//相当于5* 2的3次方
System.out.println(5 << 3);

输出结果:


所以,一个数左移多少位相当于这个数乘以2的多少次方。


右移位运算符(>>):

将十进制数字转换为二进制后,整段数字向右移动,低位溢出的需要截断,高位补符号位的数字,正数符号位为0补0,负数符号位为1补1。

比如,-6>>2结果为-2


//40右移两位
//0000 0000 0000 0000 0000 0000 0010 1000 初始值右移2位后,高位补符号位的0得:
//0000 0000 0000 0000 0000 0000 0000 1010 换算成10进制为10
//相当于5/ 2的2次方
System.out.println(40 >> 2);

//-40转换成二进制,首先需要写出对应正数40的二进制,然后将符号位置为1,符号位不变,各位取反,再加1,就得到了对应的负数的二进制
// 0000 0000 0000 0000 0000 0000 0010 1000   40的二进制
// 1000 0000 0000 0000 0000 0000 0010 1000   将符号位置为1
// 1111 1111 1111 1111 1111 1111 1101 0111   除符号位外按位取反
// 1111 1111 1111 1111 1111 1111 1101 1000   再加1,得-40的二进制
//-40右移两位
// 1111 1111 1111 1111 1111 1111 1101 1000   初始值右移2位后,高位补符号位的1得:
// 1111 1111 1111 1111 1111 1111 1111 0110   转换为十进制是先减一再按位取反,不看符号位就是其对应的正数,换算成十进制为-10
System.out.println(-40 >> 2);

输出结果:


所以,一个数右移多少位相当于这个数除以2的多少次方。


无符号右移(>>>)

将十进制数字转换为二进制后,整段数字向右移动,低位溢出的需要截断,高位补0(不管符号位是什么)

所以说,不管是负数还是正数,无符号右移之后符号位都会变为0,也就是都会变为正数。

无符号右移对于正数来说和不同右移运算符一样。

比如,-1>>>1结果为2147483647,也就是得到了Integer.MAX_VALUE


//1111 1111 1111 1111 1111 1111 1111 1111   -1的二进制,然后右移一位,高位补0
//0111 1111 1111 1111 1111 1111 1111 1111   转换为十进制为2147483647,也就是Integer.MAX_VALUE
System.out.println(-1 >>> 1);
        
//和普通右移运算符一样,得到10
System.out.println(40 >>> 2);

输出结果:



两个法则:

法则一:任何数左移(右移)32的倍数位等于该数本身。

法则二:在位移运算m<<n的计算中,若n为正数,则实际移动的位数为n%32,若n为负数,则实际移动的位数为(32+n%32),右移,同理。


常见使用场景:

1.求幂运算时,比如求m*2^n,可以直接写为 m<<n

System.out.println("3*2^3=" + (3<<3));//3*2^3=24

2.判断一个数的奇偶

n&1 == 1?”奇数”:”偶数”

奇数和偶数在二进制中的区别就是最后一位是0还是1,奇数是1,偶数是0。

因为1的二进制前面全是0,只有最后一位是1,那么这个n不管前面几位是什么,只要与0相与就一定是0,所以就保证了只看最后一位。偶数最后一位是0,与1相与就是0,奇数最后一位是1,与1相与就是1。这样就可以判断出来了。

3.不用临时变量交换两个数的值

public static int[] reverse(int[] nums){  
    int i = 0;  
    int j = nums.length-1;  
    while(j>i){  
        nums[i]= nums[i]^nums[j];  
        nums[j] = nums[j]^nums[i];  
        nums[i] = nums[i]^nums[j];  
        j--;  
        i++;  
    }  
    return nums;  
} 
原理:


猜你喜欢

转载自blog.csdn.net/wanderlustlee/article/details/80761408