计算机科学中,数字的表示方式至关重要,因为计算机内部只能识别处理二进制数据。为了在计算机中实现对整数的表示,提出了多种数值编码方式,其中最常用的是原码、反码、补码和移码。

原码(Signed Magnitude)是计算机中用来表示带符号整数的一种编码方式。在原码中,数值的符号(正负)和大小是分开表示的,其符号位用于标识符号(0表示正,1表示负),其余的位则表示该数值的绝对值。
假设我们使用n位二进制数来表示一个带符号整数,其中:
以8位原码为例,其结构如下:
登录后复制
|符号位|数值位|
|-------|-------|
| 1 | 0110 | //表示-6
| 0 | 0110 | //表示+6例如:
00000101,符号位为0,表示正数。10000101,符号位为1,表示负数。00000000和10000000。这可能导致在计算过程中出现混淆,运算时得小心识别。虽然原码简单明了,但进行加法和减法运算时会显得复杂。我们来举个例子:
考虑两个数相加:+5(00000101)和-3(10000011),我们需要进行以下步骤:
00000010(+2)。不过,如果处理两个负数相加,比如-5(10000101)和-3(10000011):
10001000(-8)。在这个过程中,需要清除对符号的关注,来确保结果正确。
减法在原码中同样复杂,通常需要将一个数的原码转换成对应的加法。
例如,计算-5(10000101)减去-3(10000011)相当于:-5 + 3。
10000101,-3的为10000011,求其绝对值差。10000010。这样的运算继承了加法的复杂性,尤其是符号的处理和加减过程中的计算负数绝对值都显得较为繁琐。
反码(One’s Complement)是一种用于表示带符号整数的编码方式。与原码相似,反码同样使用最高位作为符号位。但不同之处在于,反码是通过对原码中数值位进行“取反”来获得的:
以8位二进制数为例:
00000101,其反码也是00000101。10000101,而其反码为11111010(位数取反)。反码用于表示负数的主要目的,是希望通过简单的位操作使得计算机能够方便地进行加法与减法运算。
假设我们使用n位二进制数来表示带符号整数,其中:
例如,考虑8位反码的表示:
登录后复制
|符号位|数值位|
|-------|-------|
| 1 | 1101 | //表示-5的反码
| 0 | 0011 | //表示+3的反码00000000)和-0(11111111)。这种二义性会对后续的计算造成困扰。反码的加减法运算较为特殊,一般情况下需要注意如下几个点:
进行反码的加法运算时,公式的关键是判断符号位:
考虑两个数的加法:
登录后复制
+5(原码为00000101,反码为00000101)
+ -3(原码为10000011,反码为11111100)进行加法:
登录后复制
00000101
+ 11111100
-----------
= 11111001结果为11111001,需要对结果进行进位处理。在8位二进制中,11111001表示为-2(反码)。
减法运算在反码中可通过加反码实现,即用被减数的反码替代减法。公式是:
登录后复制
A - B = A + (-B)计算-5(反码为11111010)减去3(反码为00000011):
登录后复制
-5 - 3 = -5 + (-3) = -5 + 11111100进行加法:
登录后复制
11111010
+ 11111100
-----------
= 11110110结果为11110110,表示-8,其中符号位为1,表示结果为负数。
补码(Two’s Complement)是一种广泛用于计算机内部整数表示的编码方式。它解决了原码和反码中存在的一些问题,尤其是符号表示和结果的唯一性。补码的主要思想是将负数通过对原码取反后加1来表示,使得计算机能够以相同的硬件结构实现加、减运算。
在补码表示中,采用n位二进制数,其中:
以8位补码为例:
00000101,补码也是00000101。10000101,首先取反为01111010,然后加1得到补码01111011,即10000111。具体表示如下:
登录后复制
|符号位|数值位|
|-------|-------|
| 1 | 11111011 | //表示-5
| 0 | 00000101 | //表示+5正数的补码与原码相同,最高位为0。
负数的补码计算过程为:
例如,计算-3的补码:
00000011。11111100。11111101。因此,-3在8位补码中为11111101。
00000000。这有效避免了对零的二义性问题。-2^(n-1)到-1,而正数范围则为0到2^(n-1)-1,可能导致表示范围限制。补码是一种非常高效的数值表示,尤其在进行加法和减法时。以下是补码的加减运算规则:
进行补码加法时,两个数的补码可以直接相加。如果结果中出现进位,需要注意符号的处理。
例如,计算 +5(00000101) 和 -3(11111101) 的加法:
登录后复制
00000101 // +5
+ 11111101 // -3
-----------
00000010 // +2如果结果发生了进位,具体处理方式为:
+100(01100100) 和 +28(00011100) 的补码相加:登录后复制
01100100 // +100
+ 00011100 // +28
-----------
10000000 // 由于最高位为1,结果表示负数这个操作要注意,当符号不同的数相加时,较大的数决定了结果的符号。
减法运算可以通过补码的加法来实现,即 ( A - B ) 转换为 ( A + (-B) ),而 ( B ) 的补码就是 ( )的反码加上1。
例如,计算 -5(补码为11111011) 和 -3(补码为11111101) 的减法:
登录后复制
-5 - (-3) = -5 + 3-5 的补码:111110113 的补码:00000011登录后复制
11111011 // -5
+ 00000011 // +3 (取3的补码)
-----------
11111110 // 结果为-2移码是一种为了解决有符号数表示中的符号问题而产生的编码形式。通过对数值进行平移,移码确保了所有数值都是正数。因此,它可以将负数的表示转换为正数的范围。移码通常在某些应用中(如浮点数标准的指数部分)使用。
移码的基本想法是通过“偏移”来转换数值。在n位移码中,采用一个偏移量(K)对数值进行编码。偏移量是一个正数,通常取决于数值的范围。
对于一个具体的有符号整数x,如果要用n位移码表示,所使用的移码为:
[ \text{移码} = x + K ]
其中,K 通常为 (2^{(n-1)}),也就是将负数偏移到正数的表示空间。
例如,对于8位移码(n=8),K=127(即 (2^{(8-1)} - 1 = 127)):
假设我们用8位表示移码,K=127:
在以上例子中,所有的数值都变成了正数的表示。
移码的加减法运算比较直接。移码的加法规则通常遵循以下步骤:
对于移码(a和b)进行加法时:
例如,两个8位的移码:
登录后复制
a = 5(10000100)
b = 3(10000011)
求解 a + b = 10000100 + 10000011这两个数相加,得到:
登录后复制
10000100
+ 10000011
-----------
00000111 (进位不会影响8位,溢出不处理)结果为00000111,即原数值的6。
移码减法可以通过将被减数的移码加上减数的移码。可以通过将减数转换为移码,再进行加法运算。
例如,计算5 - 3:
登录后复制
移码(a) = +5(10000100)
移码(b) = +3(10000011)
移码(b) 变成:-3 : -3 + 127 = 124 -> 01111100
= +5 + (-3) = 10000100 + 01111100计算机内部,数值的不同表示方式有着各自的优缺点。原码直观但计算复杂,反码尝试简化减法运算却依然不能解决零的表示问题。补码则是最为广泛使用的表示法,解决了运算与表示的诸多问题。移码则在浮点数的表示中提供了一种有效的方案。