目录
一、进制转换
(1)数字进制的4个概念
(2)x进制转换成十进制
(3)十进制转换成x进制(除x取余法)
(4)二进制与八进制的相互转换
(5)二进制与十六进制的相互转换
二、原码、反码、补码
(1)机器数和真值
(2)原码、反码、补码的转换关系
(3)为什么要有反码
(4)为什么要有补码
(5)总结
一、进制转换
(1)数字进制的4个概念
以10进制数“1234”为例。
- 数码:每一位上的数,如例子中的1、2、3、4。
- 位数:数码在这个数中的位置。从右向左以0开始递增1,如例子中的数码4的位数为0、数码3的位数为1、数码2的位数为2、数码1的位数为3。
- 基数:每一位数码能表示的数字个数。如例子为10进制数,一位数码能表示0~9的数字,一共10个数,因此10进制数的基数为10。以此类推,2进制基数为2、8进制基数为8、16进制基数为16。
- 位权:在某一位上的1表示的值,位权 = 基数^位数。如例子中,数码1的位权为10^3、数码2的位权为10^2。
(2)x进制转换成十进制
进制只是一个数的不同表示方法。 x进制的每一位数码值的范围是0~x-1,能表示x个数。因此,2进制数只有数字0和1、8进制数只有数字0~7……,而在16进制数中,为了能在一位上表示两位数10~15,用字母A~F(大小写都可)代替之。
在计算机中,八进制数通常以0开头,十六进制数通常以0x(大小写都可)开头。
x进制数的十进制值 = 每一位的(数码 x 位权)之和。
举例:
① 二进制 1011 = 1 x 2^0 + 1 x 2^1 + 0 x 2^2 + 1 x 2^3 = 1 + 2 + 0 + 8 = 11。
② 八进制 1507 = 7 x 8^0 + 0 x 8^1 + 5 x 8^2 + 1 x 8^3 = 7 + 0 + 320 + 512 = 839。
③ 十六进制 7E = 14 x 16^0 + 7 x 16^1 = 14 + 112 = 126。
(3)十进制转换成x进制(除x取余法)
对十进制数除x取余(从下到上),直到被除数为0。
例如:
① 十进制11转二进制(除2取余法):
② 十进制839转八进制(除8取余法):
③ 十进制126转十六进制(除16取余法):
(4)二进制与八进制的相互转换
可以用10进制数为中介,2进制(互相转换)10进制(互相转换)8进制,从低到高每3位2进制数对应1位八进制数。
举例:2进制数01’101’011转8进制数
(二进制)011 >> (十进制)3 >> (八进制)3
(二进制)101 >> (十进制)5 >> (八进制)5
(二进制)001 >> (十进制)1 >> (八进制)1
结果:0153
(5)二进制与十六进制的相互转换
可以用10进制数为中介,2进制(互相转换)10进制(互相转换)16进制,从低到高每4位2进制数对应1位八进制数。
举例:2进制数0110’1011转16进制数
(二进制)1011 >> (十进制)11 >> (十六进制)b
(二进制)0110 >> (十进制)6 >> (十六进制)6
结果:0x6b
二、原码、反码、补码
(1)机器数和真值
机器数就是一个数在计算机中的表现形式,这个形式是符号数字化的二进制形式,其最高位是符号位,0表示正数,1表示负数。真值就是一个数真实的值。例如机器数(1)1011,它的真值为-11,而不是27。下面讲的原码、反码、补码都是机器数。
(2)原码、反码、补码的转换关系
正数的三码都是相同的,负数的三码才是不同的,因此之后说的转换讨论的是负数。三码的转换关系用下面的图来表示:
可以看到原码和补码的相互转换都是取反加1。因此,在电路设计时只要设计出取反加1,就能实现原码转补码和补码转原码了。
举一个例子:
真值:-1
原码:1000 0001
反码:1111 1110(原码的数值位取反,符号位不变)
补码:1111 1111(反码的数值位加1,符号位不变)
(3)为什么要有反码
原码是人脑最能理解的机器码,那为什么还要有反码,甚至补码呢?这一切都是为了在计算机中实现更简单高效的运算。
第一:我们希望电路更简单,让CPU的运算器中只有加法器,就能实现加、减两种基础运算。因此,可以将减法运算转换为加法运算,如:2-1 = 2 + (-1)。
第二:计算机不能区分符号和数值,如果想区分会加大电路的复杂性,因此我们需要一个不区分符号和数值,就能将符号位与数值位统一参与运算的编码形式。
再来看看原码是否能正确实现符号位与数值位统一参与运算:
1 + 1 = [0000 0001]原 + [0000 0001]原 = [0000 0010]原 = 2
当操作数都为正数,正确。
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [1000 0010]原 = -2
这个结果显然是不正确的,当有负数参与运算时,原码不能得到正确的结果。
然后再来看看反码:
1 - 1 = 1 + (-1) = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
-0就是0,结果似乎正确。但毋庸置疑的是,反码能处理有负数的运算,在下面的举例中更能证实这一点,反码计算得到的错误结果与正确结果的比较是非常有规律的。
(4)为什么要有补码
再来看看下面的几个例子:
2-1 = 2+(-1) = [0000 0010]原 + [1000 0001]原 = [0000 0010]反 + [1111 1110]反 = [0000 0000]反 = +0,比正确结果1差1。
6-2 = 6+(-2) = [0000 0110]原 + [1000 0010]原 = [0000 0110]反 + [1111 1101]反 = [0000 0011]反 = 3,比正确结果4相差1。
大家可以在试试其它的例子,会发现用反码计算出的结果都会比正确值少1,这是为什么呢?本质原因就是反码的0有-0和+0两种,因此在计算的时候会把0算两次。
比如2+(-1)可以看作给(-1)加个2,那么它每次增加1经历:-1 >> -0 >> +0,最后得到+0;比如6+(-2)可以看作给(-2)加个6,那么它每次增加1经历:-2 >> -1 >> -0 >> +0 >> 1 >> 2 >> 3,最后得到3。
因此,科学家们最终发明了补码,它将-0和+0统一为[0000 0000]补,表示0(解决了反码运算错误的问题);并将补码中的[1000 0000]补,表示-128,注意-128没有原码和反码,原码和反码比补码少一个数字-128。
(5)总结
数据在计算机中都是以补码形式存放的。原因:
- 实现了将加法和减法统一进行处理。
- 实现了将符号位和数值位统一进行处理。
- 原码和补码的相互转换,原理相同,不需要增加额外的硬件电路。