原码-反码-补码

  1. 1. 一、原码
  2. 2. 二、反码
  3. 3. 三、补码
  4. 4. 四、已知补码求原码
  5. 5. 五、普通结果验证
    1. 5.1. 1.运算1:
    2. 5.2. 2.运算2:
  6. 6. 六、-128问题
  7. 7. 七、延申:

问题:byte类型的127加上1,得到的结果是-128

一、原码

  计算机只能存储、计算二进制数据,一个byte有8个字节。那要计算两个十进制的数据,需要先将十进制数据转换为二进制数据。
例十进制:

7+1=87+1=8

转换为二进制计算:8字节,高位补0

00000111+00000001=000010000000 0111 + 0000 0001 = 0000 1000

  对于正数的计算,这个没有问题。但是对于负数如何表示?再去维护一个符号用于表示负数的代价过于高昂,于是采用了在8字节的最高位表示为1用于表示负数,只用7位表示计数。于是 -1 表示为 100000011000 0001。对于正数,不需要额外的处理,反码就是源码本身。
例十进制:

22=02-2=0

反码的出现不仅表示了负数,而且还把减法可以表示为加上一个负数,从而不再需要设计减法计数器电路。但是计算会出现如下问题:

00000010+10000010=100001000000 0010 + 1000 0010 = 1000 0100

转换为二进制可知,计算的结果为-4,计算出现了问题。

二、反码

  为了解决这个问题,出现了反码。同样,正数的反码是其本身;对于负数,就是最高位的符号位不变,其余位置取反,例如-2​二进制是100000101000 0010,则其反码为111111011111 1101
例十进制:

22=02-2=0

则二进制:

00000010原码+10000010原码0000 0010_{原码 } + 1000 0010_{原码 } \quad

00000010反码+11111101反码=11111111反码0000 0010_{反码 } + 1111 1101_{反码 } = 1111 1111_{反码 }

先转换为反码,再计算,得到的是反码的结果,但是要得到真正的结果,还需要再转为原码。

11111111反码>10000000原码1111 1111_{反码 } --> 1000 0000{原码 }

结果为-0,可见,结果是正确的,但是出现-0的结果需要处理。

三、补码

  同样,为了解决出现-0的情况,出现了补码。同样,正数的补码是其本身;对于负数,负数的补码是其反码+1。例如,-2的二进制是100000101000 0010,则其反码为111111011111 1101,则其补码为111111101111 1110
例十进制:

22=02-2=0

则二进制:

00000010原码+10000010原码0000 0010_{原码 } + 1000 0010_{原码 } \quad

00000010反码+11111101反码=11111111反码0000 0010_{反码 } + 1111 1101_{反码 } = 1111 1111_{反码 }

00000010补码+11111110补码=00000000补码0000 0010_{补码 } + 1111 1110_{补码 } = 0000 0000_{补码 }

计算十进制结果:由于最高位是0,则表示正数,补码是原码本身,所以原码为000000000000 0000,结果为0

四、已知补码求原码

已知某补码为 1111 1110,求原码

1.正数:
  如果以0开头,则证明其为正数,原码就是补码本身,如 0000 0010的补码就是本身
2.负数:
  如果以1开头,则证明为负数,先 将最高位不变,其余7位取反。

11111110补码>取反100000011111 1110_{补码 } -->取反 1000 0001

  再+1,即可得到原码(-2):

10000001+00000001=10000010原码1000 0001 + 0000 0001 = 1000 0010_{原码}

五、普通结果验证

5-3与3-5

1.运算1:

5+ (-3) (省略了反码的计算步骤)

  1. 原码:00000101原码+10000011原码0000 0101_{原码} + 1000 0011_{原码}
  2. 补码:00000101补码+11111101补码=00000010补码0000 0101_{补码} + 1111 1101_{补码} = 0000 0010_{补码}
  3. 结果:00000010补码0000 0010_{补码}是正数,原码为本身,所以十进制为2.

2.运算2:

3+(-5) (省略了反码的计算步骤)

  1. 原码:00000011原码+10000101原码0000 0011_{原码} + 1000 0101_{原码}
  2. 补码:00000011补码+11111011补码=11111110补码0000 0011_{补码} + 1111 1011_{补码} = 1111 1110_{补码}
  3. 结果:11111110补码1111 1110_{补码}是负数,原码为最高位不变,其余位取反再加1,则为:100000101000 0010,结果为-2。

六、-128问题

byte类型127+1 = -128

  1. 原码:01111111+000000010111 1111 + 0000 0001
  2. 补码:01111111+00000001=100000000111 1111 + 0000 0001 = 1000 0000
  3. 结果:-128没有原码与反码,只有补码,按照约定,补码为100000001000 0000则为-128。

七、延申:

  实际上,现代计算机中的逻辑计算电路,都是按照补码来进行存储的。所以实际的计算过程中,直接使用补码。