一、原码、反码、补码
- 二进制的最高位是符号位:0便是正数,1表示负数
- 正数的原码、反码、补码都一样
- 负数的反码=原码符号位不变,其他位取反
- 负数的补码=反码+1
- 负数的反码=补码-1
- 0的反码、补码都是0
- java没有无符号数,换言之,java中的数都是有符号的
- 在计算机运算的时候,都是以补码的方式来运算的
- 当我们看运算结果的时候,要看原码
二、位运算
1. 按位与 &
两位全为1,结果为1,否则为0
练习一:2&3 = 2
-
计算机运算用补码,因此先得到 2 和 3 的补码(int占4个字节32位,第一位是符号位)
2的原码:00000000 00000000 00000000 00000010
3的原码:00000000 00000000 00000000 00000011 -
正数的原码=补码
2的补码:00000000 00000000 00000000 00000010
3的补码:00000000 00000000 00000000 00000011 -
按位与运算的补码结果:
00000000 00000000 00000000 00000010 -
符号位是0,正数,补码和原码一样,计算机返回的原码的结果为:
00000000 00000000 00000000 00000010
2. 按位或 |
两位有一个为1,结果为1,否则为0
3. 按位异或 ^
两位是1和0结果为1,否则为0
4. 按位取反 ~
0变1,1变0
练习一:~-2 = 1
- -2的原码:10000000 00000000 00000000 00000010
- 负数的补码=反码+1
- 负数的反码=原码符号位不变,其他位取反
-2的反码:11111111 11111111 11111111 11111101
-2的补码:11111111 11111111 11111111 11111110 - ~代表按位取反,包括符号位
~-2 = 00000000 00000000 00000000 00000001 - 运算后结果的原码:00000000 00000000 00000000 00000001
练习二:~2 = -3
- 2的补码:00000000 00000000 00000000 00000010
- ~2运算结果的补码:11111111 11111111 11111111 11111101
- 运算的结果为负数,因此原码并不等于补码
- 补码-1得到反码
- 反码符号位不变,其余取反得到原码
反码:11111111 11111111 11111111 11111100
原码:10000000 00000000 00000000 00000011
5. 算术右移 >>
符号位不变,其余位右移,并用符号位补溢出的高位(最左边),正数补0,负数补1
练习一 1>>2
- 1是正数,原码和补码一样
补码=原码:00000000 00000000 00000000 00000001 - 符号位不变,整体右移两位,并用符号位补溢出的高位
- 00000000 00000000 00000000 00000000 | 01
符号位 0
补位 00
移位 01 - 本质就是 1 除以 2 再除以 2, 适用于正数
练习二 -1>>3
关键:计算机运算时用补码
-1原码:10000000 00000000 00000000 00000001
-1反码:11111111 11111111 11111111 11111110
-1补码:11111111 11111111 11111111 11111111
Integer.toBinaryString(-1) //java获得补码的方法
-1>>3:11111111 11111111 11111111 11111111 | 111
结果反码:11111111 11111111 11111111 11111110
结果原码:10000000 00000000 00000000 00000001 = -1
6. 逻辑右移 >>>
整体右移,用0补溢出的高位
练习一: -1>>>3
-1补码:11111111 11111111 11111111 11111111
-1>>>3:00011111 11111111 11111111 11111111 | 111
运算后结果是正数,原码和补码一样,因此结果是
00011111 11111111 11111111 11111111 = 536870911
7. 算数左移 <<
符号位不变,整体左移,低位补0
练习一 1<<2
00000000 00000000 00000000 00000001
左移两位变为:
00000000 00000000 00000000 00000100 = 4