1. 前言

在计算机中,数字以二进制的形式存储,分为有符号数无符号数。顾名思义,有符号数是带符号的,比如正负。无符号数是不带符号的,其范围为:0x2n10\le x\le 2^n-1

为了表示一个有符号数,除了数值位以外还应指定符号位,通常以这个数的最高位为符号位,并规定0表示正数的符号“+”;1表示负数的符号“-”。这样,数的符号在机器中也数字化了,符号位和数值位一起完整地表示有符号二进制数。

我们把一个数在机器中的表示形式称为机器数,而把它们的实际数值称为机器数的真值。计算机中,有符号的二进制数可由不同的编码形式表示,它们是原码、补码与反码。下面来详细讨论它们。

2. 原码

原码表示法是一种简单的机器数表示法,即符号和数值表示法。原码就是符号位加上真值的绝对值。以+66-66为例:

两者的真值均为:1000010,由于以0表示符号为正,以1表示符号为负。因此+66的原码为01000010-66的原码为11000010

原码的表示范围为:

(2n11)X+(2n11)-(2^{n-1}-1)\le X \le +(2^{n-1}-1)

原码简单易于理解,但是有一个缺点,那就是进行加减运算时很麻烦。参加运算的数可能为正,也可能为负。不仅要考虑运算是加还是减,还要考虑数的绝对值大小。例如,在进行两数相加时,我们要判断:

  • 如果两数同号,数值部分相加,符号不变

  • 如果两数异号,数值部分实际相减,还要对绝对值大小进行判断,才能确定实际的被减数

在原码中,零有两种表示形式:0000000010000000

正是存在以上种种弊端,我们才引入补码表示法,能够使正、负数的加法和减法运算简化成单一的相加运算。

3. 反码

正数的反码就是真值本身,负数的反码在原码的基础上,对符号位之外的数按位求反即可。反码的表示范围和原码相同:

(2n11)X+(2n11)-(2^{n-1}-1)\le X \le +(2^{n-1}-1)

在反码中,0也有两个编码,反码一般来说很少使用。

4. 补码

正数的原码、反码和补码都是相同的。求补码的步骤如下(以-66为例):

  • 表示成原码:11000010

  • 求反码:10111101

  • 加1:10111110

补码具有如下性质:

  • XX为正数时,补码和原码相同;当XX为负数时,负数的补码等于2n+X=2nX2^n+X=2^n-|X|

  • +0和-0的补码是相同的,因此在补码中,0的表示是唯一的。

补码的表示范围为:

2n1X2n1-2^{n-1}\le X \le 2^{n-1}

补码具有以下运算性质:

  • 加法:[X+Y]=[X]+[Y][X+Y]_{补}=[X]_{补}+[Y]_{补}

  • 减法:[XY]=[X][Y][X-Y]_{补}=[X]_{补}-[Y]_{补},或[XY]=[X]+[Y][X-Y]_{补}=[X]_{补}+[-Y]_{补}

5. 参考资料

《微机原理、汇编语言与接口技术》人民邮电出版社