java 逻辑运算符
java 提供的位运算(<<,>>,>>>,&,|,~,^) 。除了非(~)是一元运算符,其它都是二元操作符。
什么是一元和二元运算符?
一元运算符
操作数只有一个。例如
// 例如! 是逻辑运算符,表示相反,所以!是一元运算符。
!x
二元运算符:
有两个操作数。例如
// + 号就是二元运算符。
x+y
二进制中如何表示负数?
二进制中采用最高位是符号位的方法区分正负数。
剩下的就是这个数的绝对值部分。通过将负数转换成 二进制原码,再求原码的反码,最后求得补码即负数的二进制表示结果。
原码,反码,补码的基础概念和计算方式
1 原码
就是符号位上加上真值的绝对值,用第一位表示符号,其余位表示值,比如如果是8位二进制:
1 原码 0000 0001
-1 原码 1000 0001
第一位是符号位,因为第一位是符号位所以8位二进制的取值范围就是
[-127,127]
原码是人脑最容易理解和计算的表示方式。
2 反码
反码的表示方法
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反
可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算。
3 补码
补码的正确表示方式
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补
对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.
为什么要使用原码,反码和补码。
- 对于正数三种编码的方式都相同
[+1] = [00000001]原 = [00000001]反 = [00000001]补
- 对于负数
[-1] = [10000001]原 = [11111110]反 = [11111111]补
原因
计算机辨别符号位 会让计算机的电路设计变得非常复杂。(所以人们想出了让符号位也参与运算的方法)
计算机中减法其实是用类似加法的实现1-1 = 1 + (-1) = 0
如果直接使用原码计算
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
发现直接只用原码计算是不正确的,所以出现了反码
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.
于是补码的出现, 解决了0的符号以及两个编码的问题:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原
1 左移<<
public class test {
public static void main(String[] args) {
System.out.println(6<<2);
}
}
// 结果为24
0000 0000 0000 0000 0000 0000 0000 0110 // 6的二进制表示
0000 0000 0000 0000 0000 0000 0001 1000 // 左移两位,低位补零,换算成10进制为24
2 右移>>
public class test {
public static void main(String[] args) {
System.out.println(8>>2);
}
}
// 结果为24
0000 0000 0000 0000 0000 0000 0000 1000 // 8的二进制表示
0000 0000 0000 0000 0000 0000 0000 0010 // 右移两位,高位补零,换算成10进制为2
3 无符号右移>>>
在java中int类型占32位,可以表示一个正数,也可以表示一个负数。
正数转换成一个二进制后的最高位为 0 ,负数的二进制最高位为1
-5 的二进制表示为
1111 1111 1111 1111 1111 1111 1111 1011
分别对5进行右移3位、 -5进行右移3位和无符号右移3位:
public class Test {
public static void main(String[] args) {
System.out.println(5>>3);//结果是0
System.out.println(-5>>3);//结果是-1
System.out.println(-5>>>3);//结果是536870911
}
4 位与&
public class Test {
public static void main(String[] args) {
System.out.println(5 & 3);//结果为1
}
}
5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
1转换为二进制:0000 0000 0000 0000 0000 0000 0000 0001
5 位或|
public class Test {
public static void main(String[] args) {
System.out.println(5 | 3);//结果为7
}
}
5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
7转换为二进制:0000 0000 0000 0000 0000 0000 0000 0111
6 异或^
public class Test {
public static void main(String[] args) {
System.out.println(5 ^ 3);//结果为6
}
}
5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
6转换为二进制:0000 0000 0000 0000 0000 0000 0000 0110