关于二进制的补码,反码,正负数表示以及Java代码测试

662 阅读3分钟

Java负数的计算过程

java中最高位表示符号位,0表示正数,1表示负数

根据十进制推算二进制

以-5为例子

  1. -5的原码:1000 0101
  2. 求反码 : 1111 1010 ,符号位不进行取反
  3. 求补码(+1):1111 1011

所以-5用二进制表示为1111 1011

根据二进制逆推十进制

10001010为例子

  1. 获取补码,(-1操作)

    10001010 - 1 = 10001001

  2. 获取反码

    10001001 的反码 11110110

  3. 不看符号位,算出大小

    1110110 对应的值为 118,所以10001010的值就是-118

可以看出来,对于负数而言,因为1000 0000 后七位因为要取反,所以后七位越大反而绝对值越小,例如1111 1111 等于-1,而1111 1110 等于-2

那么对于负数而言 1000 0000 就是绝对值最大,相对值最小的了,等于-128

为什么要这样设计

首先在计算机中减法实际上是加法,2-1 == 2 + (-1),那么进行推理一下

如果都用原码

2 的原码:0000 0010

-1 的原码: 1000 0001

2 + (-1)= 10000 0011

答案是是 -3,答案错误

如果正数用原码,负数用补码

事例1

2原码:0000 0010

-1补码: 1111 1111

相加 =0000 0001 ,就等于1

事例2

10原码:0000 1010

-20补码: 1110 1100

10 + (-20) = 1111 0110 等于-10

为什么要用补码表示负数,而不是反码

或者换个说法,为什么要进行+1操作

如果不用补码,而用反码

1的原码: 0000 0001

-1的反码:1111 1110

1 + (-1) = 1111 1111 = -128

很明显答案错误

那么为什么要进行+1操作,如果你对1111 11111 +1可以发现 = 0001 0000 0000,而因为byte的大小只有8位,第9位要舍弃也就是0000 0000

因为负数最高位存在一个1,也就是说负数天然要比正数多一个1,对于正数而言,你就得额外+1才能保证正数和负数是一样大的。

关于byte取值范围

byte的取值范围为-128 ~ 127

为什么负值要大于正值?

对于最大值很容易得出:0111 1111 就等于127

但是负数不同,在1000 0000这个特殊情况下符号位是参与运算的,也就是说,1000 0000 是最小值,转化成十进制就是-128了

Java代码测试

public static void main(String[] args) {
        byte x1 = (byte)0b00000010;
        byte x2 = (byte)0b11111111;

        System.out.println("x1 = " + x1);
        System.out.println("x2 = " + x2);
        System.out.println("x1 + x2 = " +  (x1 + x2));

        byte x3 = (byte)0b11111110;
        System.out.println("x3 = " + x3);

        byte negative20 = (byte)0b11101100;
        System.out.println("negative20 : " + negative20);

        byte negative10 = (byte)0b11110110;
        System.out.println("negative10:"+negative10);

    }