1 计算计中的数据与二进制
1.1 数据
计算机中的数据总是以二元状态存在的,通常用0或1两种符号来表示,它也方便用于表示电路中的高低电平。
1.2 二进制
在计算机中是用二进制来表示数据的。二进制中1=1,2=10,4=100,8=1000。生活中,我们用得比较多的就是10进制,那么要怎么把10进制与2进制进行转换呢?
十进制转换成二进制
10进制转换成二进制
二进制转换成十进制
二进制转换成十进制
2 原码、反码和补码
在计算机中,最小的单位是位(bit),也就是二进制中的每一个数值,最小的数据存储单位是字节(byte)。一个字节由8位组成,这8位中最左侧的一位是符号位,0表示正数,1表示负数。
2.1 原码
原码就是数据的实际值,如1的原码为 0000 0001,-2的原码为1000 0010,0的原码为0000 0000。8位二进制数能表示的最大范围是[-127,127]。
2.2 反码
正数的反码是原码本身,负数的反码是在原码的基础上,符号位不变,其余位取反,如1的原码是0000 0001,反码也是0000 0001;-2的原码为1000 0010,反码为1111 1101。8位二进制数能表示的最大范围是[-127,127]。
2.3 补码
正数的补码是原码本身,负数的补码是原码的基础上符号位不变,其余位取反然后加1。8位二进制数能表示的最大范围是[-128,127]。
【注:0的原码、反码、补码是同一个!】
2.4 计算计中补码参与运算
1 + (-2) = -1,对应的原码为 0000 0001 + 1000 0010 = 1000 0011 = -3, 这是不正确的。
对应的反码为 0000 0001 + 1111 1101 = 1111 1110,转换成原码 1000 0001=-1,正确。
如果 1-1用反码计算的话,0000 0001 + 1111 1110 = 1111 1111,转换成原码就是1000 0000 = -0,是错误的表示。
所以如果用补码来计算0000 0001 + 1111 1111 = 0000 0000,对应的原码也是0000 0000=0,正确。在补码中1000 0000表示-128。
2.5 溢出
-35 + -128用补码参与运算结果是多少?
溢出
如图,计算结果超出了8位,实际结果应该是-163,但是8位能表示的范围是[-128, 127],所以上面的计算结果溢出了。取后8位即为溢出的结果93。
通过代码表示:
public static void main(String[] args) {
byte b1 = (byte) -35;
byte b2 = (byte) -128;
byte b3 = (byte) (b1 + b2);
// 这里的结果是93
System.out.println("b3 = " + b3);
// 这里也是93
System.out.println(127 - 35 + 1);
}
溢出后的结果遵循这个规则,如果-128向下溢出1位,结果是127,溢出2位,结果是126,以此类推,-128溢出35,结果就是93。同理,127向上溢出1位就是-128。
2.6 单位及换算
1B = 8b
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
3 位运算
3.1 按位与运算(&)
按位与的运算规则是:相同位都为1则为1,否则为0;
举例:
- 1 & 3的结果是多少?
1:原码:0000 0001,反码:0000 0001,补码:0000 0001;
3:原码:0000 0011,反码:0000 0011,补码:0000 0011;
所以:0000 0001 & 0000 0011 = 0000 0001,即 1 & 3 = 1;
- 1 & -3的结果是多少?
1:原码:0000 0001,反码:0000 0001,补码:0000 0001;
-3:原码:1000 0011,反码:1111 1100,补码:1111 1101;
所以:1111 1101 & 0000 0001 = 0000 0001,对应的原码为0000 0001,即1 & -3 = 1;
- -1 & -2的结果是多少?
-1:原码:1000 0001,反码:1111 1110,补码:1111 1111;
-2:原码:1000 0010,反码:1111 1101,补码:1111 1110;
所以:1111 1101 & 1111 1110 = 1111 1100,对应的原码为1000 0010,即-1 & -2 = -2;
3.2 按位或运算(|)
按位或的运算规则是:相同位只要有一个为1则为1,否则为0。
举例:
- 1 | 3的结果是多少?
1:原码:0000 0001,反码:0000 0001,补码:0000 0001;
3:原码:0000 0011,反码:0000 0011,补码:0000 0011;
所以:0000 0001 | 0000 0011 = 0000 0011,即 1 & 3 = 3;
3.3 按位异或(^)
按位异或的运算规则是:相同位相同则为0,不同则为1。
举例:
- 1 ^ 3的结果是多少?
1:原码:0000 0001,反码:0000 0001,补码:0000 0001;
3:原码:0000 0011,反码:0000 0011,补码:0000 0011;
所以:0000 0001 ^ 0000 0011 = 0000 0010,即 1 & 3 = 2;
3.4 右移运算(>>)
右移规则:符号位不变,低位(0)补齐,符号位补移出的高位(1)。
举例:
- -3 >> 5:
-3:原码:1000 0011,反码:1111 1100,补码:1111 1101;
1111 1101,右移5个,1000 0111,符号位补高位1111 1111,对应的原码1000 0001,即-3 >> 5 = -1。
- 3 >> 5
3:原码:0000 0011,反码:0000 0011,补码:0000 0011;
0000 0011右移5个,0000 0000,符号位补高位,结果还是0000 0000,即 3 >> 5 = 0;
3.5 左移运算(<<)
左移规则:符号位不变,低位补齐。
举例:
-3 << 5:
-3:原码:1000 0011,反码:1111 1100,补码:1111 1101;
1111 1101左移5位,1010 0000,对应的反码是1001 1111,原码是1110 0000,即-3 << 5 = -96。