1.2 数制及其转换
在数字电路和计算机中,只用“0”和“1”两种符号来表示信息,参与运算的数也是由“0”和“1”构成的,称为二进制数。考虑到人类计数习惯,在计算机操作时,一般都要把输入的十进制数转换为二进制数后再让计算机处理;而计算机处理的二进制结果也需要转换为便于人类识别的十进制数后显示出来。因此,需要学习不同的数制及其转换方法。
1. 数制
用数字量表示物理量的大小时,仅用一位数码往往不够用,因此经常需要用进位的方法组成多位数码来记录数的量。把多位数码中每一位的构成方法以及从低位到高位的进位规则称为数制。常用的数制有十进制、二进制、八进制和十六进制。
(1)十进制
十进制用0~9这10个符号来表示数,计数的基数是10(即使用的符号个数)。超过9的数必须用多位数表示,其中低位和相邻高位之间的关系是“逢十进一”或“借一当十”,故称为十进制。任意一个十进制数D均可展开为
其中,ki是第i位的系数,它可以是0~9这10个数码中的任何一个。若整数部分的位数是n,小数部分的位数是m,则i包含从n−1到0的所有正整数和从−1到−m的所有负整数。10i称为第i位的权值(即基数的幂次)。任何数制的数都可以按权展开,例如,十进制数按权展开的结果如下:
(125.625)10 = 1 × 102 + 2 × 101 + 5 × 100 + 6 × 10−1 + 2 × 10−2 + 5 × 10−3
若以N取代式(1.1)中的10,即可得到任意进制(N进制)数展开式的普遍形式:
(2)二进制
二进制用0和1这两个符号来表示数,计数的基数是2,权值为2i。低位和相邻高位之间的关系是“逢二进一”或“借一当二”,故称为二进制。
根据式(1.2)的规则,任意一个二进制数D均可展开为:
按权展开可以计算出二进制数表示的十进制数的大小。例如
(1101.101)2 = 1 × 23 + 1 × 22 + 0 × 21 + 1 × 20 + 1 × 2−1 + 0 × 2−2 + 1 × 2−3 = (13.625)10
(3)八进制
八进制是用0~7这8个符号来表示数的,计数的基数是8,权值为8i。低位和相邻高位之间的关系是“逢八进一”或“借一当八”,故称为八进制。
任意一个八进制数D均可展开为:
按权展开可以计算出八进制数表示的十进制数的大小。例如
(376.65)8 = 3 × 82 + 7 × 81 + 6 × 80 + 6 × 8−1 + 5 × 8−2 = (254.828125)10
(4)十六进制
十六进制是用0~9和A~F这16个符号来表示数的,计数的基数是16,权值为16i。低位和相邻高位之间的关系是“逢十六进一”或“借一当十六”,故称为十六进制。
任意一个十六进制数D均可展开为:
按权展开可以计算出十六进制表示的十进制数的大小。例如
(1FD.6C)16 = 1 × 162 + 15 × 161 + 13 × 160 + 6 × 16−1 + 12 × 16−2 = (509.421875)10
在数字电路中,为了区别不同数制表示的数,可以用括弧加数制基数下标的方式。但在计算机的编程语言中不能使用这种方式,而是使用加数制后缀或数字前缀的方式来表示不同数制的数。数制表示方式随计算机的编程语言的不同而不同,例如在Verilog HDL中,用在数的前面加前缀的方式来区别不同数制的数,其中,十进制数的前缀为D(Decimal)或d,二进制数的前缀为B(Binary)或b,八进制数的前缀为O(Octonary)或o,十六进制数的前缀为H(Hexadecimal)或h。例如
(25)10 = ’d25 = 25(十进制数的前缀可略)
(1101.101)2 = ’b1101.101
(76.56)8 = ’o76.56 (1FD.6C)16 = ’h1FD.6C
都是不同数制的表示形式。
2. 数制之间的转换
把一种数制的数转换为另一种数制的数的过程称为数制之间的转换。十进制数与二进制数之间的转换是最常用的转换。为了方便表示二进制数,有时也需要在二进制数与八进制数或二进制数与十六进制数之间转换。
(1)十进制数到N进制数的转换
十进制数的整数和小数部分到N进制数的转换方法是不同的,整数部分按除以N看余数的方法进行,小数部分按乘以N看向整数的进位进行。下面以十进制数转换为二进制数为例来讨论这个问题。
假定十进制整数为(S)10,等值的二进制数为(kn−1kn−2…k0)2,依式(1.3)可知
上式表明,若将(S)10除以2,则得到的商为kn−12n−2 + kn−22n−3 + … + k1,而余数即k0,得到转换后的二进制数的最低位(LSB)。
同理,将式(1.6)中的商除以2得到新的商,可写成
由式(1.7)看出,若将(S)10除以2的商再次除以2,则所得的余数即k1。
依此类推,反复将每次得到的商再除以2,就可以得到二进制数的每一位了。当(S)10被除到0时,得到的最后一个余数是kn−1,即为转换后的二进制数的最高位(MSB)。
例如,将(62)10转换为二进制数可按照如下方法进行:
故(62)10 = (111110)2。
其次讨论小数的转换。若(S)10是一个十进制数的小数,对应的二进制数为(0.k−1k−2…k−m)2,依式(1.3)可知
(S)10 = k−12−1 + k−22−2 + … + k−m2−m
将上式两边同乘以2得到
上式说明,将小数(S)10乘以2所得乘积的整数部分即k−1,这是转换后的二进制小数的最高位(MSB)。
同理,将乘积的小数部分再乘以2又可得到
亦即乘积的整数部分就是k−2。
依此类推,将每次乘2后所得乘积的小数部分再乘以2,便可求出二进制小数的每一位。例如,将(0.625)10转换为二进制数时可按照如下方法进行:
故(0.625)10=(0.101)2。
请读者注意,按除以2看余数的方法,将十进制数的整数部分转换为二进制数时,任何十进制整数经过若干次除以2的运算后,最终结果都可以达到0,因此十进制整数转换成二进制整数的结果是精确的。而十进制小数部分按乘以2看向整数的进位方法转换为二进制小数时,若经过若干次乘以2的运算后,其小数部分变为0时结束转换,则这些十进制小数转换成二进制小数的结果也是精确的。但是,大部分十进制小数(例如0.66)不断乘以2后,其小数部分结果将永远不会为0,因此这部分十进制小数转换为二进制小数的结果是不精确的。在这种情况下,可以按照转换精度的要求,进行若干次乘以2的运算后结束转换。
(2)N进制数转换为十进制数
将N进制数按权展开后即可转换为十进制数。例如
(3)二进制数与八进制数之间的转换
因为23 = 8,所以3位二进制数与1位八进制数有直接对应关系,即3位二进制数直接
可写为1位八进制数,而1位八进制数也可直接写为3位二进制数。例如
(11010011.1101101)2 = (323.664)8
(174.536)8 = (1111100.10101111)2
(4)二进制数与十六进制数的转换
因为24 = 16,所以4位二进制数与1位十六进制数有直接对应关系,即4位二进制数直接可写为1位十六进制数,而1位十六进制数也可直接写为4位二进制数。例如
(11010011.1101101)2 = (D3.DA)16
(17C.5F)16 = (101111100.01011111)2
十进制数到八进制数(或十六进制数)的转换,可以用整数部分按除8(或除16)看余数,小数部分按乘以8(或乘以16)看向整数进位的方法进行,但采用这种转换方法时运算比较烦琐。一般采用把十进制数首先转换为二进制数后,再将二进制数写为八进制数或十六进制数方法比较简单。例如
(62.625)10 = (111110.101)2 = (76.5)8 = (3E.A)16