原码、反码、补码、移码

《计算机组成原理》上讲得不清楚。我总结了一下,希望对大家有帮助。

原码、反码、补码和移码,都是计算机对数的一种编码,其目的是方便地实现数据的存储和计算。

我们讨论的都是符号数。首先给出真值和机器数的定义。

符号数的真值,是指直接用正号“+”和负号“-”来表示符号的二进制数。机器数,是把符号位和数值位一起编码的二进制数。一般用最高有效位来表示数的符号,正数用0表示,负数用1表示。例如,真值+1001,对应的机器数为01001;真值-1001,对应的机器数为11001。

原码

原码,即符号位加上二进制数的绝对值,最高位表示符号位,对于正数,符号位记为0,对于负数,符号位记为1,其余各位表示数值部分。例如,真值+1001,对应的原码为01001;真值-1001,对应的原码为11001。

接下来讨论原码表示的数的范围。我们从简单的入手,假如有一个两位二进制数,那么它有四种状态,即00或01或10或11,它可以表示1、2、3、4,若把最高位看作符号位(把它看作原码),则可以表示-1、-0、+0、+1。推广得到,对于n位的二进制数,其原码表示的数的范围为:-(2(n-1)-1)~-0~+0~(2(n-1)-1)。

从原码的定义可以看到,这是一种很简单的编码。原码的存储也很简单,只要增加一个符号位就可以了。那么,它在计算中表现如何呢?

我们不考虑溢出。经过简单的计算可以知道,对于两个正数或两个负数之间的加法,原码是没有问题的。但对于正数和负数之间的加法,则出现了错误。例如,用8位二进制数的原码表示,

2 + (-3) = 00000010 + 10000011 = 100000101 = -5

2 + (-2) = 00000010 + 10000010 = 10000100 = -4

为了解决这个问题,我们引入了补码。

补码

我们先以钟表对时为例说明补码的概念。假设现在的标准时间为4点整,而有一只表已经7点了,为了校准时间,可以采用两种方法:一是将时针退7 - 4 = 3格;一是将时针向前拨12 - 3 = 9格。这两种方法都能对准到4点,由此看出,减3和加9是等价的。就是说9是(-3)对12的补码,可以用数学公式表示为-3 = +9 (mod 12)。mod 12的意思就是12为模数,这个“模”表示被丢掉的数值。上式在数学上称为同余式。

上例中之所以7 - 3和7 + 9 (mod 12)等价,原因就是表指针超过12时,将12自动丢掉,最后得到16 - 12 = 4。

从这里可以得到一个启示,就是负数用补码表示时,可以把减法转化为加法。这样,在计算机中实现起来就比较方便。只需设计一个加法器就能实现数据的加减运算。

举个例子,

9 + (-6) = 01001 + 10110(原码) = 01001 + 11010(补码) = 100011 = 3

最前面的进位1丢弃了。其实应该倒过来求,已知100011和01001,求-6的补码。通过观察验证,我们得到了补码的求法:

在补码表示法中,正数的补码表示同原码和反码的表示是相同的,而负数的补码表示却不同。对于负数的补码,其符号位为1,而数值部分是将其原码数值部分“按位求反,末位加1”而得到的。例如,真值+1001,对应的补码为01001;真值-1001,对应的补码为10111。

接下来讨论补码表示的数的范围。继续从简单的入手,补码00、01、11分别表示0、1、-1,由数的补码表示与真值的关系(按权展开并相加)得,补码10表示-21。推广得到,对于n位二进制数,其补码表示的数的范围为:-2(n-1)~(2^(n-1)-1)。

补码的存储很简单,增加一个符号位,并用它的定义求出其数值位。

对于补码的计算,我们验证一下上面的式子,

2 - 3 = 2 + (-3) = 00000010 + 11111101 = 11111111 = -1

2 - 2 = 2 + (-2) = 00000010 + 11111110 = 00000000 = 0

说明补码能实现数据的加减运算。

反码

反码是连接原码和补码的桥梁。通过反码可以很容易地求出补码。接下来给出反码的定义。

用反码表示时,左边第一位也是符号位,符号位为0代表正数,符号位为1代表负数,对于负数,反码的数值是将其原码数值按位求反而得到的,而对于正数其反码和原码相同。例如,真值+1001,对应的反码为01001;真值-1001,对应的反码为10110。

反码表示的数的范围,通过类比,发现跟原码一样,即对于n位二进制数,其反码表示的数的范围为:-(2(n-1)-1)~-0~+0~(2(n-1)-1)。

移码

对于浮点数,补码可以用于尾数的表示,但用补码来表示阶码,则有些不妥。因为补码有正负号,不便于比较两个指数的大小。对于8位二进制数的补码,它的范围是-128~+127。如果我们加上128,则它的范围变为0~255。这样我们就可以方便地比较两个指数的大小了。例如,-127的补码是10000001,加上128变成00000001,而0的补码是00000000,加上128变成10000000。我们把最高位看作数值位,则可以明显地看出0大于-127。因此我们引入移码。

移码通常用于表示浮点数的阶码。阶码是个k位的整数,最高位为符号位。移码的一般定义是:[e]移 = 2^k + e,其中[e]移为机器数,2k是一个固定的偏移值常数,e是真值且其范围为-2k <= e < 2^k。例如,k = 4,真值+1001,对应的移码为1,1001;真值-1001,对应的移码为0,0111。

在IEEE 32位浮点格式中,阶码字段k = 8位,固定的偏移值常数不是2k,而是2(k-1) - 1 = 2^7 - 1 = 127。这样,指数真值e的范围为-127~+128,阶码E的范围为0~255。由于要除去E用全0和全1表示零和无穷大的特殊情况,E的范围变为1~254,真正的指数值e的范围变为-126~+127。

posted on 2016-02-12 21:29  LunaElf  阅读(3836)  评论(0)    收藏  举报