0%

原码、反码和补码

本篇文章主要学习记录原码、反码以及补码的相关知识。

原码

计算机为了表示负数,在二进制数值前面增加一位符号位(即最高位为符号位):正数该位为0,负数该位为1,其余位表示数值的大小。

比如,10的二进制原码表示为0 1010,-10的二进制原码表示为1 1010

这种编码方式被称之为原码,原码的优点比较明显,就是简单直观,容易被人理解

存在的问题

当正数+正数时,比如5+2,即0 0101 + 0 0010 = 0 0111,原码0 0111表示十进制中的7,即5+2=7。此时没有任何问题。

当正数+负数时,比如5+(-2),即0 0101 + 1 0010 = 1 0111,原码1 0111表示十进制中的-7,即5+(-2)=-7,显然是不正确的。

原码这种编码方式仅支持正数+正数(即加法操作),而对于正数+负数(即减法操作)这种情况,显然不支持。

反码

反码是基于原码计算得来,表示方式是:正数的反码是其本身。负数的反码是在其原码的基础上,符号位不变,其余各个位取反。

举例说明,10的二进制反码表示为0 1010,-10的二进制反码表示为1 0101

反码计算的规则:

  1. 反码运算时,其符号位与数值一起参加运算。
  2. 反码的符号位相加后,如果有进位出现,则要把它送回最低位去相加(循环进位)。
  3. 用反码运算,其运算结果亦为反码。在转换为真值时,若符号位为0,数位不变;若符号位为1,应将结果各个位取反才是其真值。

比如5+(-2),反码表示为0 0101 + 1 1101 = 0 0011,即5+(-2)=3。

再看一个(-5)+2,反码表示为1 1010 + 0 0010 = 1 1100,反码1 1100对应原码1 0011,其结果为-3。

存在的问题

当5+(-5)时,即0 0101 + 1 1010 = 1 1111,反码1 1111对应原码1 0000,其真值为-0。尽管+0和-0是一样的,但是0带符号是没有意义的。

反码虽然解决了减法的问题,但是却没有解决0的符号问题。

补码

补码是在原码和反码的基础上衍生出来的,补码的表示方法是:正数的补码就是其本身。负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1(即在反码的基础上+1)。

补码计算的规则:

  1. 补码运算时,其符号位与数值一起参加运算。
  2. 补码的符号位相加后,如果有进位出现,则进位被舍弃。
  3. 用补码运算,其运算结果亦为补码。在转换成原码时,如果是正数,其补码就是原码;如果是负数,该补码的补码就是其原码。

先来看一下5+(-5),即0 0101 + 1 1011 = 0 0000。补码0 0000对应十进制为0。没有问题。

再来看一下5+(-6),即0 0101 + 1 1010 = 1 1111。补码1 1111对应原码1 0001,即5+(-6)=-1。也没有问题。

有了补码,0的表达方式就唯一了,如果是8位的话,那么就是固定的0000 0000。同时,补码的取值范围也从原码和反码的[-127, 127](即[11111111, 01111111]变成了[-128, 127],其中补码1000 0000来表示-128。

总结

  1. 正数的反码是其本身,负数的反码是在原码的基础上,除符号位外,其余位取反。

  2. 正数的补码是其本身,负数的补码是在原码的基础上,除符号位外,其余位取反,然后+1(即在反码的基础上+1)。

  3. 负数的补码的补码是其原码。

参考文章:

  1. 漫话:为什么计算机用补码存储数据?
您的支持将鼓励我继续创作!