左移和右移
无符号左移? | Java没有无符号左移 |
---|---|
无符号右移 | 左边补0 |
有符号右移 | 左边用原符号位补位 即正数补0效果同无符号右移、负数补1 |
有符号左移 | 右边补0 |
import org.junit.Test;public class TestAaaBinary {@Testpublic void test01() {//调用 JDK 的自带方法 toBinaryString 输出二进制数test01(false);//自己写的打印,结果与上面是一样的test01(true);}private void test01(boolean print) {int num_5 = 5;int num_5_2 = -5;System.out.println("无符号右移:正数");for (int i = 0; i >> i, print);}System.out.println("无符号右移:负数");for (int i = 0; i >> i, print);}System.out.println("有符号右移:正数");for (int i = 0; i > i, print);}System.out.println("有符号右移:负数");for (int i = 0; i > i, print);}System.out.println("有符号左移:正数");for (int i = 0; i < 32; i++) {print(num_5 << i, print);}System.out.println("有符号左移:负数");for (int i = 0; i < 32; i++) {print(num_5_2 <= 0; i--) {System.out.print((num & (1 << i)) == 0 ? "0" : "1");}System.out.println();}}
输出如下:
无符号右移:正数000000000000000000000000000001010000000000000000000000000000001000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101无符号右移:负数111111111111111111111111111110110111111111111111111111111111110100111111111111111111111111111110000111111111111111111111111111110000111111111111111111111111111100000111111111111111111111111111000000111111111111111111111111110000000111111111111111111111111100000000111111111111111111111111000000000111111111111111111111110000000000111111111111111111111100000000000111111111111111111111000000000000111111111111111111110000000000000111111111111111111100000000000000111111111111111111000000000000000111111111111111110000000000000000111111111111111100000000000000000111111111111111000000000000000000111111111111110000000000000000000111111111111100000000000000000000111111111111000000000000000000000111111111110000000000000000000000111111111100000000000000000000000111111111000000000000000000000000111111110000000000000000000000000111111100000000000000000000000000111111000000000000000000000000000111110000000000000000000000000000111100000000000000000000000000000111000000000000000000000000000000110000000000000000000000000000000111111111111111111111111111111011有符号右移:正数000000000000000000000000000001010000000000000000000000000000001000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101有符号右移:负数111111111111111111111111111110111111111111111111111111111111110111111111111111111111111111111110111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111011有符号左移:正数000000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000001010000000000000000000000000000101000000000000000000000000000010100000000000000000000000000000010000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000101有符号左移:负数111111111111111111111111111110111111111111111111111111111111011011111111111111111111111111101100111111111111111111111111110110001111111111111111111111111011000011111111111111111111111101100000111111111111111111111110110000001111111111111111111111011000000011111111111111111111101100000000111111111111111111110110000000001111111111111111111011000000000011111111111111111101100000000000111111111111111110110000000000001111111111111111011000000000000011111111111111101100000000000000111111111111110110000000000000001111111111111011000000000000000011111111111101100000000000000000111111111110110000000000000000001111111111011000000000000000000011111111101100000000000000000000111111110110000000000000000000001111111011000000000000000000000011111101100000000000000000000000111110110000000000000000000000001111011000000000000000000000000011101100000000000000000000000000110110000000000000000000000000001011000000000000000000000000000001100000000000000000000000000000110000000000000000000000000000001000000000000000000000000000000011111111111111111111111111111011
此外,根据上面的代码,我们还可以经过测试得出
- int 类型位移32位、64位还是它本身
- long 类型位移64位还是它本身
原码&反码&补码
看上面的输出可能会有疑问
整型正数5
的二进制是00000000 00000000 00000000 00000101
整型负数5
的二进制是10000000 00000000 00000000 00000101
那为什么上文中对于-5
的二进制输出是11111111 11111111 11111111 11111011
呢?
先公布一下答案:这里输出的都是补码,计算机是使用补码做计算的。
下面详细解释为什么使用补码
计算机中只计算加法
- 减法可以化为加法:比如
5-4
转化为5+(-4)
- 乘法可以转化为加法和位移算法
- 除法可以先转化为乘法再转化
只算加法简化了电路的设计
但是在二进制运算下,一个正数加上其相反数并不等于0,比如0000 0001 + 1000 0001 = -2
因此出现了反码,而数字本身我们叫做原码。
- 正数的反码是它本身
- 负数的反码是:符号位不变,其他位取反,比如
-5
的反码是11111111 11111111 11111111 11111010
反码存在的问题:
- 比如
5 + (-5) = 0
,二进制是00000000 00000101 + 11111111 11111010 = 11111111 11111111
全1表示0(负0) - 而
0 + 0 = 0
,二进制00000000 00000000
全0也表示0(正0)
还有更好的方案吗?答案就是补码
- 正数的补码是本身
- 负数的补码是反码+1,例如
-5
的补码是11111111 11111111 11111111 11111011
上文提到过
补码只有全0表示0一种情况,相比反码又简化了电路的设计
参考下面的代码:
public void test02() { int num = 5; System.out.println("正数5的补码是原码本身"); print(num); System.out.println("正数5取反就是其相反数-5的反码"); print(~num); System.out.println("-5用补码表示,是反码+1"); print(-num);}
输出:
正数5的补码是原码本身00000000000000000000000000000101正数5取反就是其相反数-5的反码11111111111111111111111111111010-5用补码表示,是反码+111111111111111111111111111111011
扩展:整型的最大值和最小值
@Testpublic void test03() { System.out.println("整型最大值是正 2的31次方-1 补码就是其本身"); print(Integer.MAX_VALUE); System.out.println(); System.out.println("整型最小值的补码"); print(Integer.MIN_VALUE); System.out.println("补码取反"); print(~Integer.MIN_VALUE); System.out.println("补码取反+1 就是整型最小值的相反数 即2的31次方 因此整型最小值是负 2的31次方");}
输出:
整型最大值是正 2的31次方-1 补码就是其本身01111111111111111111111111111111整型最小值的补码10000000000000000000000000000000补码取反01111111111111111111111111111111补码取反+1 就是整型最小值的相反数 即2的31次方 因此整型最小值是负 2的31次方