原码、反码、补码、移码的定义以及各自的优缺点

1、引言

计算机使用二进制存储数字。

简单来讲,由0和1两个数字组成的序列,称为二进制数。

在计算机科学中,二进制数主要有四种形式:原码、反码、补码、移码

二进制数是由0和1两个数字组成的序列,这个序列中的每一个数字都有它自己的权重。从右

往左,这个序列每一位上的数字对应的权重依次是2^{0}2^{1}2^{2}2^{3}\cdot \cdot \cdot

例如,二进制数0101表示正整数5

计算过程(二进制转化为十进制):1 \times 2^{0}+ 0 \times 2^{1}+1 \times 2^{2}+0 \times 2^{3} =1+4 =5

二进制数不仅能表示整数,而且能表示小数。

以小数点为分界点,小数点左侧,从右往左,每一位上的数字对应的权重依次是2^{0}2^{1}2^{2}

2^{3}\cdot \cdot \cdot ;小数点右侧,从左往右,每一位上的数字对应的权重依次是2^{-1}2^{-2}2^{-3}\cdot \cdot \cdot

例如,二进制数0.1110表示小数0.875

计算过程(二进制转化成十进制):0 \times 2^{0}+ 1 \times 2^{-1}+ 1 \times 2^{-2}+1 \times 2^{-3}+0 \times 2^{-4}

=0.5+0.25+0.125=0.875


2、原码

虽然二进制数能表示整数和小数,但是只能表示正整数和大于零的小数。

为了能表示负整数和小于零的小数,引入原码。

规定二进制数中权重最大的位最高位

规定最高位是符号位的二进制数,称为原码

符号位的数字是0,这样的二进制数表示正数。

符号位的数字是1,这样的二进制数表示负数。

原码的二进制布局示意图,如下图所示。

原码 0XXXX \cdots = 二进制数XXXX \cdots

原码 1XXXX \cdots = (-1) \times 二进制数XXXX \cdots

例如,原码0101表示正整数5

注释:符号位是0,数值位是101。原码 0101=   1 \times 2^{0}+ 0 \times 2^{1}+1 \times 2^{2}=5

再比如,原码1101表示负整数-5。

注释:符号位是1,数值位是101。原码 1101= (-1)\times(1 \times 2^{0}+ 0 \times 2^{1}+1 \times 2^{2})=- 5

再比如,原码101.1表示负数 -1.5 

注释:符号位是1,数值位是01.1。原码101.1=(-1)\times(0 \times 2^{1}+ 1 \times 2^{0}+1 \times 2^{-1})=- 1.5

原码的优点

能表示正数和负数。

原码的缺点

不能直接参与算术运算。

例如,原码0101表示正整数5,原码1001表示负整数-1,原码0101与原码1001按位相加

得到原码1110,原码1110表示负整数-6。

按位相加的规则:0+0=0,0+1=1,1+0=1,1+1=0向前(右)进一位

计算过程如下图所示。

显然,5+(-1)= 4 ≠ -6,两个原码按位相加的结果是错误的。

因此,原码不能直接参与算术运算。

此外,原码存在正零和负零。

符号位是0,其余各位都是零的原码,表示正零。

符号位是1,其余各位都是零的原码,表示负零。

例如,原码0000表示正零,原码1000表示负零。


3、反码

虽然原码能表示正数和负数,但是不能直接参与算术运算。为了解决这个问题,引入补码。

补码能直接参与算术运算。

在介绍补码之前,先给出反码的定义。

反码视为原码和补码之间的过渡形式

反码与补码的关系:反码的最低位加1,得到补码

反码与原码的关系:反码的最高位和原码的最高位相同,正数的反码和原码完全相同。

负数的反码,由负数的原码按照一定规则转化得到。负数的原码最高位(符号位)保持不变,

其余各位取反,按照这样的规则得到负数的反码。

例如,反码0101表示正整数5

注释:符号位是0,说明这个反码表示正数。正数的反码和原码完全相同。因此,反码0101

对应原码0101,原码0101表示正整数5。

再比如,反码1101表示负整数-2

注释:符号位是1,说明这个反码表示负数。负数的反码和原码的符号位相同,其余各位取反,

得到原码1010。原码1010代表负整数-2

再比如,反码101.0表示负数 -2.5

注释:符号位是1,说明这个反码表示负数。负数的反码和原码的符号位相同,其余各位取反,

得到原码110.1。原码110.1表示负数-2.5

反码的优点

不仅能表示正数和负数,而且能直接参与算术运算。

例如,反码0101代表正整数5,反码1001代表负整数-6。反码0101与反码1001按位相加,

得到反码1110,反码1110代表负整数-1。

注释:反码0101的符号位是0,反码0101对应原码0101,原码0101表示正整数5。

注释:反码1001的符号位是1,反码1001对应原码1110,原码1110表示负整数-6。

注释:反码1110的符号位是1,反码1110对应原码1001,原码1001表示负整数-1。

按位相加的规则:0+0=0,0+1=1,1+0=1,1+1=0向前(右)进一位

计算过程如下图所示。

显然,5+(-6)= -1 ,两个反码按位相加的结果是正确的。

因此,反码能直接参与算术运算。

反码的缺点

虽然反码能直接参与算术运算,但是存在一个弊端。两个反码相加的过程中,如果符号位

出现进位(1+1=0),那么最低位需要加1

例如,反码1110与反码0011按位相加,得到反码0001。由于这两个反码相加的过程中,

符号位出现进位,最低位需要加1。最终的计算结果是反码0010。反码0010表示正整数2。

显然,(-1)+(3)= 2,两个反码按位相加的结果是正确的。

注释:反码1110表示负整数-1,反码0011表示正整数3,反码0010表示正整数2。

计算过程如下图所示。

再比如,反码1110.0与反码0011按位相加,得到反码0001.0。由于这两个反码相加的过程中,

符号位出现进位,最低位需要加1。最终的计算结果是反码0001.1。反码0001.1表示正数1.5。

显然,(-1.5)+(3)= 1.5,两个反码按位相加的结果是正确的。

注释:反码1110.0表示负数-1.5,反码0011表示正整数3,反码0001.1表示正数1.5。

计算过程如下图所示。

此外,反码存在正零和负零。

符号位是0,其余各位都是0的反码,表示正零。

符号位是1,其余各位都是1的反码,表示负零。

例如,反码0000表示正零,反码1111表示负零。

注释:反码0000的符号位是0,反码0000对应原码0000,原码0000表示正零。

注释:反码1111的符号位是1,反码1111对应原码1000,原码1000表示负零。


4、补码

虽然反码能直接参与算术运算,但是存在一些弊端。两个反码相加的过程中,如果符号位

出现进位(1+1=0),那么最低位需要加1。此外,反码存在正零和负零。为了解决这些问题,

引入补码。

补码能直接参与算术运算。而且,两个补码相加的过程中,当符号位出现进位(1+1=0),

最低位不需要加1。这大大提高了运算效率,降低了算术运算过程的复杂度。此外,补码

不存在正零和负零之分。使用补码表示零,只有一种表示形式:每一位上的数字都是零。

补码与反码的关系:反码的最低位加1,得到补码

补码与原码的关系:码的最高位和原码的最高位相同,正数的补码和原码完全相同。

负数的补码,由负数的原码按照一定规则转化得到。负数的原码最高位(符号位)保持不变,

其余各位取反,然后最低位加1,按照这样的规则得到负数的补码。

例如,补码0101表示正整数5

注释:符号位是0,说明这个补码表示正数。正数的补码和原码完全相同。因此,补码0101

对应原码0101,原码0101表示正整数5。

再比如,补码1001表示负整数-7

注释:符号位是1,说明这个补码是负数。负数的补码和原码的符号位相同,其余各位取反,

然后最低位加1,得到原码1111。原码1111表示负整数-7。

再比如,补码1001.1表示负数-6.5

注释:符号位是1,说明这个补码是负数。负数的补码和原码的符号位相同,其余各位取反,

然后最低位加1,得到原码1110.1。原码1110.1表示负数-6.5。

补码的优点

能表示正数和负数。

能直接参与算术运算。与反码相比,算术运算过程的复杂度更低。

例如,补码0101代表正整数5,补码1011代表负整数-5。补码0101与补码1011按位相加,

得到补码0000。这两个补码相加的过程中,符号位出现进位。与反码不同,在符号位出现

进位的情况下,补码的最低位不需要加1。最终的计算结果就是补码0000。补码0000表示零。

显然,(5)+(-5)= 0,两个补码按位相加的结果是正确的。

注释:补码0101的符号位是0,补码0101对应原码0101,原码0101表示正整数5。

注释:补码1011的符号位是1,补码1011对应原码1101,原码1101表示负整数-5。

注释:假设机器字长是4bit,补码0101和补码1011按位相加,得到补码0000。这两个

补码相加的过程中,符号位出现进位(1+1=0)。受到机器字长的限制,二进制数的

位数不超过4位,补码0000的符号位左侧的位是不存在的。因此,最终得到的补码就是0000。

计算过程如下图所示。

再比如,补码0101.1代表正数5.5,补码1011代表负整数-5。补码0101.1与补码1011按位相加,

得到补码0000.1。这两个补码相加的过程中,符号位出现进位(1+1=0)。补码0000.1的符号位

左侧的位是不存在的。因此,最终得到的补码是0000.1。补码0000.1表示正数0.5。

显然,5.5+(-5)=0.5,两个补码按位相加的结果是正确的。

注释:补码0101.1至少占用5bit。不妨设机器字长是5bit,并且二进制数最低位的权重是2^{-1}

注释:补码0101.1的符号位是0,补码0101.1对应原码0101.1,原码0101.1表示正数5.5。

注释:事先假设机器字长是5bit,并且二进制数最低位的权重是2^{-1}。因此,补码1011事实上

是补码1011.0。补码1011.0的符号位是1,补码1011.0表示负数。补码1011.0对应原码1101.0,

原码1101.0表示负整数-5。

注释:补码0000.1的符号位是0,补码0000.1对应原码0000.1,原码0000.1表示正整数0.5。

计算过程如下图所示。

此外,使用补码表示零,只有一种表示形式:每一位上的数字都是零。

补码不会出现正零和负零之分。

与原码及反码相比,补码在算术运算、零的表示这两方面更具优势。因此,计算机普遍使用

补码存储数据,尤其是整数类型数据。然而,对于小数类型数据,受到机器字长的限制,

如果计算机使用补码存储小数类型的数据,那么实际上存储的可能是小数的近似值

举例来讲,小数0.1对应的二进制数是一个无限循环的由0和1组成的序列0.0001100110011

0011••• 。计算机使用二进制存储数据,假设使用补码的形式去表示这个二进制数,那么这个

二进制数对应的补码的位数必然无限的。由于受到机器字长的限制,计算机实际只能保留有限

位数的补码。这意味着计算机实际存储的是0.1的近似值。

当然,某些小数能被精确表示。例如,小数0.5对应的二进制数是0.1。不妨设机器字长是4bit,

并且最低位的权重是2^(-2)。小数0.1对应的二进制数事实上是00.10。二进制数00.10对应原码

00.10,原码00.10对应补码00.10。因此,某些小数能被精确表示。

事实上,计算机不使用补码去存储小数类型数据,而是使用“移码+原码”的组合形式去存储小数

类型数据。这里不展开介绍,关于小数类型数据的存储方式,敬请关注后续推文。

总之,计算机使用补码存储整数类型数据,使用补码对整数类型数据进行算术运算。计算机使用

“移码+原码”的组合形式去存储小数类型数据,使用这种组合形式对小数类型数据进行算术运算。

注意事项

特别规定:符号位是1,其余各位都是0的补码,表示负整数 -2^{n}。其中,n代表补码的数值位

的位数。例如,补码1000表示负整数-8。补码1000 0000表示负整数-128。

这种特殊的补码的二进制布局示意图,如下图所示。

这种特殊的补码没有对应的原码,或者说这样的补码不能转化为原码。

补码的缺点

任意两个补码不能直接比较大小。

具体来说,任意两个补码比较大小,必须先判断两者的符号位。

如果两者的符号位不同,那么符号位是0的补码一定大于符号位是1的补码。

如果两者的符号位相同,那么也不能直接判断两者的大小。需要根据符号位的具体情况,

分类讨论。

例如,补码0001和补码0111的符号位都是0,补码0001小于补码0111。

注释:补码0001表示正整数1,补码0111表示正整数7。

再比如,补码1111和补码1001的符号位都是1,补码1111大于补码1001。

注释:补码1111表示负整数-1,补码1001表示负整数-7。


5、移码

为了能直接判断两个二进制数的大小,引入移码。

移码是一种特殊的二进制数。

移码不能直接参与算术运算。但是,与补码相比,移码具有一个突出优势,那就是任意两个

移码能直接比较大小。具体来说,移码0000 ~ 1111构成一个严格单调增大的数列{ 0000,0001,

0010,0011,0100,0101,0110,0111,1000,1001,1010,1011,1100,1101,1110,

1111}。

换而言之,移码0000 < 移码0001 < 移码0010 < ··· < 移码1110 < 移码1111

移码与补码的关系:移码,由补码按照一定规则转化得到。补码的符号位取反,其余各位保持

不变,按照这样的规则得到移码这样的移码,称为“标准的移码”,偏移值是2^{k-1},其中k

移码的位数。

移码有符号位。但是,移码的符号位是1表示正数,移码的符号位是0表示负数。

例如,移码0101表示负整数-3

注释:移码0101对应补码1101,补码1101对应原码1011,原码1011表示负整数-3。

再比如,移码1111表示正整数7

注释:移码1111对应补码0111,补码0111对应原码0111,原码0111表示正整数7。

再比如,移码0000表示负整数-128

注释:移码0000对应补码1000,补码1000表示负整数-128。

移码的优点

任意两个移码能直接比较大小。

移码的用途

在计算机科学中,利用移码的独特优势,使用移码表示浮点数的指数域。这样的做法,有助于快速

比较两个浮点数的指数大小。

移码的缺点

不能直接参与算术运算。

此外,值得一提的是,在某些特定的情况下,会使用非标准的移码标准的移码与非标准的移码的

区别在于偏移值

偏移值等于2^{k-1}k是移码的位数)的移码,称为标准的移码。

偏移值不等于2^{k-1}k是移码的位数)的移码,称为非标准的移码。

IEEE 754技术标准选用的移码是非标准的,它的偏移值是2^{k-1}-1其中,k是移码的位数

无论是标准的移码,还是非标准的移码,都能直接比较大小。

偏移值不会对移码的大小判断造成影响

标准的移码转化为十进制数的计算公式:把标准的移码视为“不带符号位的二进制数”,把“不带

符号位的二进制数”转化为十进制数,再减去偏移值2^{k-1}k是移码的位数),最后的计算结果

就是标准的移码所对应的十进制数。

非标准的移码转化为十进制数的计算公式:把非标准的移码视为“不带符号位的二进制数”,把

“不带符号位的二进制数”转化为十进制数,再减去偏移值(可能是2^{k-1}-1,根据实际情况

确定),得到的计算结果就是非标准的移码所对应的十进制数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值