目录
二.BCD码(Binary-Coded Decimal,用二进制编码的十进制)
首先需要知道以下几个概念:
•位权:每一位所占权重。例如下图,K0的权重是10^0
•基数:每个数码位所用到的不同符号的个数,r进制的基数为r。例如10进制数的基数就是10(十进制使用的符号为0~9),二进制数的基数就是2(0~1)
计算机中能够处理的数是二进制数,原因如下:
① 只需要使用有两个稳定状态的物理器件就可以表示二进制0或1。
② 0,1刚好对应对应逻辑值假,真。方便实现逻辑运算。
③ 可很方便地使用逻辑门电路实现算术运算。
一.各进制间的相互转换
1.各进制转化为10进制
转换规则如下:
例如:
下面表格建议多熟悉熟悉,看到2^n就需要知道是多少
2.二进制和八进制,十六进制之间地相互转化
① 二进制转换为八进制:每3位为一组,每组转换为对应的八进制符号
注:从小数点开始,从前往后/从后往前每3位划分,如果不满三位就补0:
② 二进制转换为十六进制:每4位为一组,每组转换为对应的十六进制符号
③ 八进制转换为二进制:每位八进制对应3位二进制
④ 十六进制转换为二进制:每位十六进制对应4位二进制
表示2进制数,也表示2进制数。
其余进制也有其他表示方法:
3.十进制转换为其他进制
① 十进制转换为二进制
对于整数部分,将十进制数,不断除以基数r,直到商为0为止。
对于小数部分,运算规则如下:小数部分*基数r得到的乘积结果的整数部分,对应的值,将剩余的小数部分继续乘基数,得到的值,依次类推:
具体以0.3为例,可以看到10进制表示的0.3没办法用2进制数精确的表示:
补充:可以使用更加快捷的方法---拼凑法
例如,对于十进制数260.75:
整数部分:260=256+4=2^8+2^2
小数部分:0.75=0.25+0.5=2^-2+2^-1
总结:
① 整数部分要用除基取余法,小数部分要用乘积取整法。
② 任何二进制小数都能用十进制表示。
十进制的小数不一定能通过二进制精确表示。
② 十进制转换为八进制/十六进制
当我们熟悉了上面快捷的方法,完全可以先将十进制转化为二进制,再将二进制转换为十六进制,例如下图:260.75转换为二进制为100000100.11
将他转换为8进制:
将他转换为16进制:
二.BCD码(Binary-Coded Decimal,用二进制编码的十进制)
我们可以用4bit的信息,表示1个十进制位,因为4个2进制位可以表示2^4=16种状态,而这16种状态就足够表示10进制中的0~9(10种状态)了。其余的6种状态是冗余的。
1.8421码
如下图所示,4种状态分别表示10进制的8,4,2,1。
如果表示5:4+1=5,所以8421码为0101。
依次类推,就可以得到0~9与8421码的映射关系:
十进制转换为8421码:
手算方法:先用十进制得到结果,再将结果转换为对应的8421码。
计算机中使用的方法:
① 计算机会把加数和被加数1000,0101送到算术逻辑单元(ALU),算术逻辑单元进行加法运算后,得到结果:1101,将二进制转化为10进制,得13。
可以观察到,8421码中合法的编码区间为0000~1001,1010~1111没有定义,1100已经超出合法范围,为了使运算结果满足8421码的定义:
当运算得到的结果落在了10~18:9+9(1010~10010),也就是不合法的范围,可以在运算结果的基础上+6,使得结果向高位进一,如下图所示,高4位表示1,低4位表示3(0011),就可以表示十进制数13。
同理,9(1001)+9(1001)=18(10010),超出了8421码能够表示的范围,+6修正:
得到:1 1000,1对应的8421码为1,1000对应的8421码为8,合起来结果也为18。
2.余3码
4个二进制数对应16种状态,将16种状态的其中10种分别映射到0~9这几个数字。像8421码,就是将10种状态映射到0000~1001:
如果换一种映射方式,肯定会得到不一样的结果,例如余3码的映射规则就是:8421码的基础上加3:8321码+0011B
在8421码中,每个二进制位都有固定的权值(8,4,2,1),但在余3码中,每个二进制位并没有固定的权值,所以8421码被称为有权码,而余3码被称为无权码。
3.2421码
2421码也是一种有权码,从高到低,每一位对应的权值为2,4,2,1。
2421码对应的映射关系如下:
注意:
2421码中0~4对应编码的第1位都是0,而5~9对应编码的第1位都是1。这是为了统一2421码的编码策略。例如,5可以表示为0101,1011,为了避免歧义的发生,2421码规定5~9首位必须为1。
三.无符号整数
无符号整数,即“自然数”,0,1,2,3.....,在C语言中,只要用“unsigned”就可以定义无符号整数:
1.无符号整数在计算机内部的表示
计算机内的机器字长限制了每次可以进行运算的bit位,也限制了通用寄存器的长度。例如,某计算机机器字长为8位,那么他最多能同时进行8位运算(现在个人计算机的机器字长通常是64位或32位):
通用寄存器只能存8位2进制数:
对于无符号整数0,存入到寄存器需要扩充为8位:
依次类推,无符号整数256用2进制表示为1 0000 0000 ,超出了寄存器能存储的二进制数的长度,所以寄存器只能保存低8位。
总结:
① 全部二进制位都是数值位,没有符号位,第 i 位的位权是。
② n bit 无符号整数表示范围 0~,超出则溢出,意味着该计算机无法一次处理这么多③ 可以表示的最小的数 全0,可以表示的最大的数 全1。
2.无符号整数的加法/减法运算
无符号整数的加法:从最低位开始,按位相加,并往更高位进位。
无符号整数的减法:
① “被减数”不变,“减数”全部位 按位取反、末位+1,减法变加法
② 从最低位开始,按位相加,并往更高位进位也就是要把减法操作化作等价的加法操作,原因在于,加法电路造价便宜,减法电路造价昂贵。
例如,对于99-9:
计算机内部进行的操作如下:
① “减数”全部位 按位取反,末位+1。
② 将“A”与“变形得来的B”进行加法操作。
只保留低8位,但是不影响计算结果,0101 1010转化为10进制数为90
四.带符号整数
数学中的带符号整数,就是“整数”,-2,-1,0,1,2,3,4,在C语言中表示为:
以机器字长8bit为例:
1.带符号整数在计算机内部的表示
•原码
8位2进制数,将第1位作为符号位,将剩余位作为数值位,用于表示真值的绝对值。符号位为0,则为正数,符号位为1,则为负数。
① 若机器字长为n+1位,带符号整数的原码表示范围:
② 原码的真值0有两种形式:+0和-0:[+0]原=0,0000000 [-0]原=1,0000000
原码的缺点:
如下图所示,如果想实现+19+(-19),将两者的原码直接相加,得到的结果是错误的,正确的结果应该是19-19=0才对。
这是因为符号位参与了运算,对于原码的加减,符号位是不能参与运算的,需要设计更复杂的硬件电路才能处理。
怎么才能解决这个问题呢----补码表示法,如果用补码表示各个参与运算的数,符号位就能参与运算,并且得出正确的结果。
所以,计算机内部,所有带符号整数的加/减法都要先转换为补码。
•反码
反码是专门用于原码到补码的转换的:
若原码是一个正数:
原码,反码,补码的表示都是一样的,保持不变即可。
若原码是一个负数:
① 转换为反码:符号位不变,数值位取反
② 在得到的数末尾+1
-100同理:
注意:
① 原码,反码,补码的最高位都反映了符号。
② 原码转换为反码,反码转换为原码的操作都是相同的,即符号位保持不变,数值位按位取反。
③ 如果考试的时候,需要将补码转化为反码,不建议直接(补码-1),可以先将补码转换为原码,再将原码转换为反码。
④ 原码与补码之间快速转换的方法:
如果原码是正数:原码和补码相同。
如果原码是负数:原码转换为补码和补码转换为原码的方法相同,即:
从右往左找到第一个1,这个1左边的所有“数值位”按位取反。
例如,原码为1,1100100
从右往左第一个1:1,1100100,“1”左边的所有"数值位"全部按位取反:1,0011100,即得到补码。
补码转原码也是同样的操作,自己可以试试。
•补码
补码的加法运算:
从最低位开始,按位相加(符号位参与运算)并往更高位进位。
注:补码的数值位不能解读为“位权”。如下图所示,正数的补码可以解释为“位权”,但是"负数"则不行。
对于两个负数相加,用补码运算也能得到得到正确结果:
补码的减法运算:
由于减法电路制造成本较昂贵,所以可以用等价的加法电路替代减法电路,思路如下:
A-B=A+(-B)
[A]补-[B]补=[A]补+[-B]补
类比无符号整数的"减法"操作:
① "被减数"不变,"减数"全部位按位取反,末位+1,减法变加法。
② 从最低位开始,按位相加,并往更高位进位。
这里的"减数"对应的就是补码减法中的[B]补,两者的操作是一摸一样的。也就是说,无论是实现无符号整数的减法,还是有符号整数的补码减法,在计算机看来都是一样的,我们可以使用同一套电路就能实现这两种操作。
怎么实现[B]补和[-B]补的相互转换:将全部位按位取反,再在末位+1。
例如下图:
补充:更快的手算方法
与补码,原码之间的相互转换类似:从右往左找到第1个"1",以这个"1"为界,将其左边部分(包括符号位)全部取反,右边部分保持不变。(注:原码与补码之间的相互转换是"1"的左边的全部"数值位"按位取反)
知道了[B]补--->[-B]补,那么就可以将补码减法转化为等价的加法操作了,举个例子:
•原码,反码和补码的特性对比
1.原码
合法表示范围:
若用n+1bit表示原码,原码的数值位由n个bit表示,那么n个比特能够表示的数值范围是0~,再加上1个bit的符号位,所以原码的表示范围:
最大的数:
0,111....111=
最小的数:
1,111....111=
真值0的表示方式:
[+0]原=0,000....000 [-0]原=1,000....000
2.反码
合法表示范围:
最大的数:
0,111....111 =
最小的数:
1,000....000 =
真值0的表示方式:
[+0]反=0,000....000 [-0]反=1,111....111
3.补码
合法表示范围:
补码的合法表示范围要比原码多一个负数,也就是说,如果使用8bit表示原,反,补码的话,原码的合法表示范围是-127~127,补码的合法表示范围是-128~127。
重要:
最大的数:
0,111...111=
最小的数:
重要:1,000....000=
这里是定义的,只需要记住这一特殊存在即可。用8bit表示补码,最小的数是-128;用8bit表示原码,最小的数是-127,也就是说-128没有与之对应的原码,原码没有办法表示这一特殊的值。
真值0的表示方式:
重要:真值0只有唯一的补码:[0]补=0,000...000
可以这样理解,另一个数1,000....000,被用作表示了,即被用作表示最小值了。
4.无符号整数
合法表示范围:
最大的数:
1111...111=
最小的数:
0000...000=0
真值0的表示:
0000...000
总结:
•移码
补码的基础上将符号位取反。
注:移码只能用于表示整数,而原码,反码,补码可以用于表示小数。
① 移码和补码相同,只有1种真值0的表示方式,以8bit为例:[0]移=1,0000000
② 移码的合法表示范围也和补码相同,比原码多一位负数:
观察一下移码从-128到127的二进制表示,刚好是无符号整数0~255。利用这个特点,移码表示的整数可以很方便地用硬件电路对比大小。移码通常用于表示浮点数的阶码。
用几种码表示的机器数:
五.定点小数
定点数分为定点整数和定点小数,定点整数就是带符号整数。之前在学习定点整数时,我们默认了一点,就是小数点固定在最后一位。小数点前面一位是2^0,再往前为2^1,依次类推,所以“位权”是根据这一位与小数的相对位置决定的。
定点整数可以用原码,反码,补码,移码表示,而定点小数只能用原码,反码,补码表示:
定点小数中,小数点的位置隐含在符号位之后,同理,每一位数的“位权”也是根据这个数与小数点的相对位置决定的,例如小数点后第一位为2^-1,小数点后第二位为2^-2,依次类推:
1.定点小数的原码表示
注:定点整数的符号位后面通常由","隔开,而定点小数的符号位后面通常由“.”隔开。
2.定点小数的反码/补码表示
怎么用定点小数的原码得到定点小数的反码和补码呢,其实操作和定点整数一模一样。
3.定点小数的加/减运算
定点小数的加/减法运算也和定点整数的操作一模一样:
定点小数补码的加法:
从最低位开始,按位相加(符号位参与运算),并往更高位进位。
定点小数补码的减法:
① “被减数”不变,“减数”全部位按位取反、末位+1,减法变加法
② 从最低位开始,按位相加,并往更高位进位
举个例子:
和定点整数的处理逻辑是一样的
对比整数补码的加法操作和小数补码的加法操作。下面的例子中,寄存器里面的值是一模一样的,只是在定点整数和定点小数中,对应位置的“位权”不同而已。
也就是说,在计算机看来,不管是对于定点整数还是定点小数,都是用同一套逻辑来处理的,只是人为解读的对应位置的位权不同而已。
4.定点小数中的原码,反码和补码
•原码
定点小数的原码,数值部分能表示的最大值为 全1 ,即2^-1+2^-2+2^-3....,利用等比数列求和公式,则数值部分最大为
再结合前面的符号位,得到定点小数的表示范围:
最大的数:
0,111....111=
最小的数:
1,111....111=
定点小数原码对真值0的表示同样有两种:
[+0]原 = 0,000...000
[-0]原 = 1,000...000
•反码
定点小数的表示范围:
最大的数:
0,111....111=
最小的数:
1,000...000=
定点小数原码对真值0的表示同样有两种:
[+0]反 = 0,000...000
[-0]反 = 1,111...111
•补码
合法的表示范围:
重要:
最大的数:
0,111....111=
最小的数:
重要:1.000...000=-1,
和定点整数的补码相同,这个特殊的值无法用定点小数的原码表示出来。
真值0的表示:
[0]补 = 0,000...000,真值0只有一种补码。
对比定点整数和定点小数:
5.定点小数的位置扩展
定点整数和定点小数还有一个很重要的区别,就是位置扩展时,两者的拓展位置不同。来看下面的例子,由于定点小数的小数点在符号位的后面,所以当4bit要拓展为8bit时,是在二进制数的最后进行扩展:
对于定点整数,如果要将4bit拓展为8bit,则需要在符号位后面进行拓展: