左移和右移

无符号左移?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次方