Java的位运算 符详解
运算符:运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
-
Java有六种运算符,分别是:
算术运算符 赋值运算符 比较运算符(关系运算符) 逻辑运算符 位运算符 三元运算符
其中位运算符效率最高,因为电脑执行的是机器语言,也就是有“0”和“1”组成的二进制数,而位运算是对机器码二进制直接进行操作 。
这里我只和大家分享java的7种 位运算符 。不对的地方请大家多多包涵。
注:在计算机在存储数据时,存储的是数据的二进制补码
1、与运算符
与运算符用符号 “&” 表示,其使用规律是:
只有两个操作数的二进制位都为1,结果才为1,否则结果为0。
// 正数 与运算
public class WeiYunSuan {
public static void main(String[] args) {
int a = 2;
int b = 3;
System.out.println("a和b 与运算的结果:"+(a & b));
}
}
运行结果:
下面进行分析:(因为 int 是4个字节,32位,这里我只列出 8 位,正数符号位是0)
“a”的值是 2,转换成二进制就是0000 0010
“b”的值是 3,转换成二进制就是0000 0011
结果 0000 0010 即:2。
因为正数的 原码 和 补码 一样,所以运算时可直接进行操作。
接下来我们让两负数进行运算:
//负数 与运算
public class WeiYunSuan {
public static void main(String[] args) {
int a = -2;
int b = -3;
System.out.println("a和b 与运算的结果:"+(a & b));
}
}
运算结果为:
下面进行分析:(负数的符号位是 1,且负数的原码、反码、补码不一致)
“a”的值是 -2,转换成二进制就是:1000 0000 0000 0000 0000 0000 0000 0010
反码:1111 1111 1111 1111 1111 1111 1111 1101
补码:1111 1111 1111 1111 1111 1111 1111 1110
“b”的值是 -3,转换成二进制就是:1000 0000 0000 0000 0000 0000 0000 0011
反码:1111 1111 1111 1111 1111 1111 1111 1100
补码:1111 1111 1111 1111 1111 1111 1111 1101
在与运算时,要对补码进行操作,且符号位也要进行运算,结果:
1111 1111 1111 1111 1111 1111 1111 1100
算下来的结果是补码,其反码:1111 1111 1111 1111 1111 1111 1111 1011
原码:1000 0000 0000 0000 0000 0000 0000 0100 即:-4
因为计算机在存储数据时,是对数据的二进制的补码进行存储,所以在进行与运算时,我们要对数据的二进制补码进行操作,算下来的结果也是补码,因此我们要对运算结果进行 转反码(-1),在进行取反操作(符号位不变)。最后得出的结果就是控制台输出的结果了。
最后我们让两个一正一负进行运算
//一正一负
public class WeiYunSuan {
public static void main(String[] args) {
int a = 1;
int b = -2;
System.out.println("a和b 与运算的结果:"+(a & b));
}
}
运算结果为:
下面进行分析:
“a”的值是 1,转换成二进制就是:0000 0000 0000 0000 0000 0000 0000 0001
“b”的值是 -2,转换成二进制就是:1000 0000 0000 0000 0000 0000 0000 0010
反码:1111 1111 1111 1111 1111 1111 1111 1101
补码:1111 1111 1111 1111 1111 1111 1111 1110
在与运算时,要对补码进行操作,且符号位也要进行运算,结果:
0000 0000 0000 0000 0000 0000 0000 0000 即:0
从运算的二进制补码中可以看出:正数的原码和补码一样,且最高位符号位为0。所以正数在与负数进行与运算时,最后结果永远是 0 或者 正数。
2、或运算符
或运算符用符号 “|” 表示,其运算规律是:
只有两个操作数的二进制位都为0,那么结果才是0,否则就为1。
其运算的操作数转换和上述的与运算符道理一致,只是运算规律不一样。
这里我要强调的是,两个一正一负的数进行或运算(与运算的区别)
public class WeiYunSuan {
public static void main(String[] args) {
int a = 5;
int b = -6;
System.out.println(a+"和"+b +"或运算的结果:"+(a ^ b)));
}
}
运算结果:
下面进行分析:
“a”的值是 5,转换成二进制就是:0000 0000 0000 0000 0000 0000 0000 0101
“b”的值是 -6,转换成二进制就是:1000 0000 0000 0000 0000 0000 0000 0110
反码:1111 1111 1111 1111 1111 1111 1111 1001
补码:1111 1111 1111 1111 1111 1111 1111 1010
在或运算时,要对补码进行操作,且符号位也要进行运算,结果:
1111 1111 1111 1111 1111 1111 1111 1111
反码:1111 1111 1111 1111 1111 1111 1111 1110
原码:1000 0000 0000 0000 0000 0000 0000 0001 即:-1
所以,一正一负的两个数进行或运算,得出的结果永远是负数。和与运算相反。
3、异或运算符
异或运算符是用符号 “^” 表示的,其运算规律是:
两个操作数的二进制位中,相同则结果为0,如:1^1=0,0^0=0
不同则结果为1。如:1^0=1
具体运算过程和上述的步骤一样,大家在运算时只需注意异或的运算规律。这里我只列出代码:
// 两正数运算
public class WeiYunSuan {
public static void main(String[] args) {
int a = 8;
int b = 5;
System.out.println(a+"和"+b +"异或运算的结果:"+(a ^ b));
}
}
运算结果为:
// 两负数
public class WeiYunSuan {
public static void main(String[] args) {
int a = -8;
int b = -5;
System.out.println(a+"和"+b +"异或运算的结果:"+(a ^ b));
}
}
运算结果:
// 一正一负
public class WeiYunSuan {
public static void main(String[] args) {
int a = 5;
int b = -8;
System.out.println(a+"和"+b +"异或运算的结果:"+(a ^ b));
}
}
运算结果:
异或运算大家会发现:
两正数运算和两负数运算,结果肯定是 0 或者 正数。两一正一负进行运算,结果一定是负数。
4、取反运算符
取反运算符用符号 “~” 表示,其运算规律是:
正数取反:各二进制码按补码每个位进行取反
负数取反:各二进制码按补码每个位进行取反
代码演示:
public class WeiYunSuan {
public static void main(String[] args) {
int a = 6;
System.out.println(a +"取反运算的结果:"+ ~a );
}
}
运算结果:
下面进行分析:
“a”的值是 6,转换成二进制就是:0000 0000 0000 0000 0000 0000 0000 0110
补码和原码一样,按位进行取反: 1111 1111 1111 1111 1111 1111 1111 1001
反码: 1111 1111 1111 1111 1111 1111 1111 1000
原码: 1000 0000 0000 0000 0000 0000 0000 0111 即:-7
5、左移运算符
左移运算符用符号 “<<” 表示,其运算规律是:
a << 2 表示 a 的二进制码往左移两位。
不管是正数还是负数,从高位往左移,空缺位补 0 ,高位丢弃(符号位也丢弃)。
代码演示:
public class WeiYunSuan {
public static void main(String[] args) {
int a = 6;
System.out.println(a +"左移29位运算的结果:"+ (a<<29) );
}
}
运算结果:
下面进行分析:
“a”的值是 6,转换成二进制就是:0000 0000 0000 0000 0000 0000 0000 0110
往左移29位,变为:1100 0000 0000 0000 0000 0000 0000 0000
反码: 1011 1111 1111 1111 1111 1111 1111 1111
原码: 1100 0000 0000 0000 0000 0000 0000 0000 即:-2^30
6、右移运算符
右移运算符用符号 “>>” 表示,其运算规律是:
右移的话,低位舍去,空缺位根据操作数的最高位(即:符号位)进行补位。
最高位是 0,则补 0;最高位是 1,则补 1。
代码演示:
public class WeiYunSuan {
public static void main(String[] args) {
int a = -6;
System.out.println(a +"右移1位运算的结果:"+ (a>>1) );
}
}
运算结果:
下面进行分析:
“a”的值是 -6,转换成二进制就是:1000 0000 0000 0000 0000 0000 0000 0110
反码:1111 1111 1111 1111 1111 1111 1111 1001
补码:1111 1111 1111 1111 1111 1111 1111 1010
右移 1 位,为:1111 1111 1111 1111 1111 1111 1111 1101
反码: 1111 1111 1111 1111 1111 1111 1111 1100
原码: 1000 0000 0000 0000 0000 0000 0000 0011 即:-3
7、无符号右移
无符号右移运算符的符号用 “>>>” 表示,其运算规律是:
顾名思义:就是被移位的二进制数,最高位不管是 0 还是 1,空缺位都补 0。
代码演示:
public class WeiYunSuan {
public static void main(String[] args) {
int a = -6;
System.out.println(a +"无符号右移29位运算的结果:"+ (a>>>29) );
}
}
运算结果:
下面进行分析:
“a”的值是 -6,转换成二进制就是:1000 0000 0000 0000 0000 0000 0000 0110
反码:1111 1111 1111 1111 1111 1111 1111 1001
补码:1111 1111 1111 1111 1111 1111 1111 1010
无符号右移 29 位,为:0000 0000 0000 0000 0000 0000 0000 0111 即:7
总结
最后一个问题: 2 在左移运算时的规律,大家想想是什么?
以上七种位运算符的运算,便是我在学习过程中的理解。其实,只要记住:电脑在进行运算时使用机器语言进行运算,也就是用二进制的补码进行存储运算。所以大家在做这方面的题目时要注意负数的原码反码和补码。