在计算机内,表示有符号数的方法有三种,即原码、反码、补码,由于它们是数在计算机内部的表示,因而统称为机器数。与机器数的概念相对应,人类日常书写的数称为真数。
原码、反码、补码三种表示法规定:使用1位二进制位来表示数的正负性,“0”表示“正”,“1”表示“负”,该位是整个二进制串的最高位,被称为符号位。
【法则】
(1)正数的原码、反码、补码三者相同。
(2)负数的反码是对其原码除符号位外逐位取反,补码是在其反码的末位加1(注意:加1时,即使不断向前进位也不能波及符号位,即符号位不受影响,例如补码1111 1111加1后应变为1000 0000,而不是0000 0000)。
值得一提的是,由于无符号数不含负数,因而对于一个无符号数来说,其原码、反码、补码形式上是相同的,对其谈三种表示法,尤其是谈补码表示法是毫无意义的。
为什么要创造“补码”呢?补码的出现就是为了解决“负数在计算机中的运算”这一问题的,补码的引入能简化运算电路的设计。关于这一点,稍后会有说明。
【原码】
以8位二进制位为例,若以原码方式来表示,可以表示的有符号数范围为-127—+127,共255个数。
8位二进制位的0、1排列组合情况共有256种,为何只表示了255个数呢?少的一个去哪了?
原来,使用原码表示法表示数值0会有两种写法,分别是0000 0000和1000 0000,“0000 0000”是所谓“正零”,而“1000 0000”是所谓“负零”。我们都知道零既非正数也非负数,但原码表示法却很自然地搞出了+0和-0,虽然荒唐,但不无道理。零这个数有两种写法的现象,正好暴露了原码表示法的缺陷。
以下给出几个关键数值的原码表示:
真数
-127
可以看出,如果按照二进制串0000 0000、0000 0001、0000 0010、……、1111 1110、1111 1111不断加一的规则顺序来考虑,表示的有符号数顺序为:
0(正零)、1、2、……、126、127、0(负零)、-1、-2、……、-126、-127
从数轴角度来说,这是先正半轴递增,后负半轴递减的顺序。
【反码】
以8位二进制位为例,若以反码方式来表示,可以表示的有符号数范围为-127—+127,共255个数。
同样,8位二进制位的0、1排列组合情况共有256种,为何只表示了255个数呢?少的一个去哪了?
原因是这样的,由于原码表示法的“零”有两种写法,相应地,反码表示法的“零”也便有了两种写法,又是“零”多占了一个名额。由此可见,反码表示法也是有缺陷的。
以下给出几个关键数值的反码表示:
真数
-127
如果按照二进制串0000 0000、0000 0001、0000 0010、……、1111 1110、1111 1111不断加一的规则顺序来考虑,表示的有符号数顺序为:
0(正零)、1、2、……、126、127、-127、-126、……、-2、-1、0(负零)
从数轴角度来说,这是先正半轴递增,后负半轴也递增的顺序。
【补码】
以8位二进制位为例,若以补码方式来表示,可以表示的有符号数范围为-128—+127,共256个数。
对于“零”,补码只有一种表示法。
以下给出几个关键数值的补码表示:
真数
-128
-127
如果按照二进制串0000 0000、0000 0001、0000 0010、……、1111 1110、1111 1111不断加一的规则顺序来考虑,表示的有符号数顺序为:
0、1、2、……、126、127、-128、-127、-126、……、-2、-1
从数轴角度来说,这是先正半轴递增,后负半轴也递增的顺序。
综上所述,只有补码表示法的零是唯一的,这避免了在运算时引起混乱。
现代计算机中,在机器级层面表示数一般都用补码表示法,使用补码的好处有二:
(1)补码只有一个零。
(2)补码的减法运算可以转化为加法运算。
关于第二条好处,博主稍微深入解释一下。
现代计算机都是电子计算机,进行运算的部件都是电子器件,由于加、减法的运算本质不同,要实现这两种不同运算需设计两套运算电路,我们姑且称其为“加法器”和“减法器”。如果能将加、减法两种运算化归为一种运算,无疑会降低运算电路设计的复杂度,采用补码就能将加、减法合并为加法运算,从而只需要一套运算电路便可进行两种运算,所以,如今的计算机中只有“加法器”,而没有“减法器”。
【其他】
这里介绍一下补码的算术运算。
(1)算式 127-128=-1 将转化为127的补码与-128的补码相加。
127补码为:0111 1111,-128补码为1000 0000,
+
1111 1111恰是-1的补码。
(2)算式 127-1=126 将转化为127的补码与-1的补码相加。
127补码为:0111 1111,-1补码为1111 1111,
+
0111 1110恰是126的补码。
需要注意的是:前面说到,已知负数的反码,求补码时,在末尾加1,即使不断向前进位,也不可波及符号位,这是为了不影响数本身的奇偶性;但在进行补码加法运算时,不仅符号位参与了运算,还要将数值部分的进位也包括进来一同参与运算,最终才能得到正确的结果。