一、什么是位运算符
位运算符主要针对二进制的运算,就像加减乘除适用与十进制,而位运算符就是针对两个二进制数的位进行逻辑运算
二、位运算符有哪些
操作符 | 说明 |
---|---|
& | 与 |
| | 或 |
~ | 取反 |
^ | 异或 |
>> | 右移 |
<< | 左移 |
>>> | 无符号右移 |
三、各个位运算符的详解
3.1 与运算符(&)
与运算符用符号“&”表示:
运算规则:两个操作数中的 位 都为1,结果才为1,否则结果为0,例如下面的程序段。
package com.leely;
public class Test {
public static void main(String[] args) {
byte a = 11; // 二进制为 00001011
byte b = 22; // 二进制为 00010110
System.out.println("位运算符 a&b 的结果为:"+(a&b));
//都为1 才为 1
//(a&b) 的结果为 : 00000010 转换为10进制等于 2
//位运算符 a&b 的结果为:2
}
}
3.2 或运算符(|)
或运算符用符号 | 表示 :
运算规则:两个操作数中的 位 如果相对应位都是 0,则结果为 0,否则为 1,例如下面的程序段。
package com.leely;
public class Test {
public static void main(String[] args) {
byte a = 11; // 二进制为 00001011
byte b = 22; // 二进制为 00010110
System.out.println("位运算符 a|b 的结果为:"+(a|b));
//全 0 才为 0
//(a|b) 的结果为 : 00011111 转换为十进制等于 31
//位运算符 a|b 的结果为:31
}
}
**注意点 : 在或运算符中 全1 也为 1 **
3.3 取反运算符(~)
取反运算符用符号 ~ 表示 :
运算规则:操作数中的位,如果 为 0 则取反为1 如果为 1 则取反为 0 ,例如下面的程序段。
package com.leely;
public class Test {
public static void main(String[] args) {
byte a = 11; // 二进制为 00001011
byte b = 22; // 二进制为 00010110
System.out.println("位运算符 ~a 的结果为:"+(~a));
System.out.println("位运算符 ~b 的结果为:"+(~b));
// 0 为 1 , 1 为 0
// 0 为 1 , 1 为 0
//(~a) 的结果为 : 11110100 转换为十进制等于 -12
//(~b) 的结果为 : 11101001 转换为十进制等于 -23
//位运算符 ~a 的结果为:-12
//位运算符 ~b 的结果为:-23
}
}
为什么11110100转换为十进制等于 -12,11101001 转换为十进制等与-23 ,这就要从二进制的存储方式讲起。计算机并不直接存储二进制原码,而是存储二进制的补码,正数的补码就是原码,负数的补码,是“符号位不变,原码取反码再加一”,负数输出时,将补码逆向译成原码。
这样去解释会比较绕 ,我们先了解下什么是原码, 反码和补码。
3.3.1 原码
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:
[1111 1111 , 0111 1111]
即
[-127 , 127]
原码是人脑最容易理解和计算的表示方式.
3.3.2 反码
反码的表示方法是:
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反
可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.
3.3.3 补码
补码的表示方法是:
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补
对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.
由此我们可以了解 11110100 在计算机看来就是负数的补码 ,在输出的时候,计算机对其进行转换
11110100 补码
转换为反码:
减 1:
11110011
转换为原码:
取反:
10001100
结果为 : -12
3.4 异或运算符 (^)
异或运算符用符号“^”表示
运算规则:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。
package com.leely;
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 12;
System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
System.out.println("a^b 的值为:"+ Integer.toBinaryString(a^b));
//结果
// a的二进制值为:1010
// b的二进制值为:1100
// a^b 的值为: 0110
}
}
3.5 右位移运算符(>>)
右移运算符用符号 ”>>“表示
运算规则:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),如果该数为正数则高位的空位补零,如果为负数,则高位补1。
package com.leely;
public class Test {
public static void main(String[] args) {
int a = 10;
int b = -10;
System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
System.out.println("a>>2 的值为:"+ Integer.toBinaryString(a>>2));
System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
System.out.println("b>>2 的值为:"+ Integer.toBinaryString(b>>2));
//结果
// a的二进制值为:00001010
// a>>2 的值为: 00000010
// b的二进制值为:11111111111111111111111111110110
// b>>2 的值为: 11111111111111111111111111111101
}
}
3.6 左位移运算符 (<<)
左位移运算符用符号“<<”表示
运算规则: 按二进制形式把所有的数字向左移动对应的位数, 高位移出(舍弃),正负数一样,低位的空位补零
package com.leely;
public class Test {
public static void main(String[] args) {
int a = 10;
int b = -10;
System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
System.out.println("a<<2 的值为:"+ Integer.toBinaryString(a<<2));
System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
System.out.println("b<<2 的值为:"+ Integer.toBinaryString(b<<2));
//结果
// a的二进制值为:1010
// a<<2 的值为:101000
// b的二进制值为:11111111111111111111111111110110
// b<<2 的值为:11111111111111111111111111011000
}
}
3.7 无符号右位移符 (>>>)
无符号右位移符用 符号“>>>”表示
运算规则:表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0
package com.leely;
public class Test {
public static void main(String[] args) {
int a = 10;
int b = -10;
System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
System.out.println("a>>>2 的值为:"+ Integer.toBinaryString(a>>>2));
System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
System.out.println("b>>>2 的值为:"+ Integer.toBinaryString(b>>>3));
//结果
// a的二进制值为:1010
// a>>>2 的值为:0010
// b的二进制值为:11111111111111111111111111110110
// b>>>2 的值为:00011111111111111111111111111110
}
}
四、复合位赋值运算符
所有的二进制位运算符都有一种将赋值与位运算 组合在一起的简写形式。复合位赋值运算符由赋值运算符与位运算符组合而成。下表列出了组合后的复合位赋值运算符。
复合位赋值运算符
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
&= | 按位与赋值 | num1 &= num2 | 等价于 num 1=num 1 & num2 |
` | =` | 按位或赋值 | num1 |= num2 |
^= | 按位异或赋值 | num1 ^= num2 | 等价于 num 1=num 1 ^ num2 |
«= | 按位左移赋值 | num1 «= num2 | 等价于 num 1=num 1 « num2 |
»= | 按位右移赋值 | num1 »= num2 | 等价于 num 1=num 1 » num2 |