2.1.2 进制转换
对于任何一个数,我们可以用不同的进位制表示。比如:十进制数(57)10可以用二进制表示为(111001)2,也可以用八进制表示为(71)8,也可以用十六进制表示为(39)16,它们所代表的数值都是一样的。
在进制中,各位数字所表示值的大小不仅与该数字本身的大小有关,还与该数字所在的位置有关,我们将每一固定位置对应的单位值称为位权。例如十进制第1位的位权为100,第2位的位权为101;而二进制第1位的位权为20,第2位的位权为21,对于N进制数,整数部分第i位的位权为Ni-1,而小数部分第j位的位权为N-j。如十进制数时3721可以写为每一位数字与其位权之积的和:
3721=3×103+7×102+2×101+1×100
其他进制数也可以这样表示。
1.其他进制转换为十进制
用按权展开法,把一个任意R进制数anan-1...a1a0.a-1a-2...a-m转换成十进制数,其十进制数值为每一位数字与其位权之积的和。
an×Rn+an-1×Rn-1+…+a1×R1+a0×R0+a-1×R-1+a-2×R-2+…+a-m×R-m
(1)二进制转换为十进制
二进制数的基数为2,第0位的权值是20,第1位的权值是21……。所以,设有一个二进制数:101100100,写成按位权展开的形式,并计算结果:
1×28+0×27+1×26+1×25+0×24+0×23+1×22+0×21+0×20=356
0乘以任何值都是0,所以忽略值为0的位:
1×28+1×26+1×25+1×22=356
(2)八进制转换为十进制
八进制就是逢八进一。八进制数采用0~7表达一个数。八进制数第0位的权值为80,第1位权值为81,第2位权值为82……。所以,设有一个八进制数:1507,转换为十进制为:839,可以直接计算如下:
1×83+5×82+0×81+7×80=839
(3)十六进制转换为十进制
十六进制就是逢十六进一,但只有0~9这10个数字,所以用A~F这6个字母来分别表示10~15。字母不区分大小写。十六进制数的第0位的权值为160,第1位的权值为161,第2位的权值162……。所以,假设有一个十六进制数2AF5,直接计算就是:
2×163+A×162+F×161+5×160=10997
此处可以看出,所有进制均可换算成十进制,关键在于各自的权值不同。
2.十进制转换为二进制
十进制数转换为二进制数时,由于整数和小数的转换方法不同,所以先将十进制数的整数部分和小数部分分别转换后,再加以合并。
十进制整数转换为二进制整数采用“除2取余,逆序排列”法。具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为0,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列。例如,将(46)10转换为二进制(101110)2的过程如图2-1所示。
图2-1 十进制转换为二进制过程示意图
假设十进制整数A转换后得二进制数为edcba,那么二进制数按权展开,得:
e×24+d×23+c×22+b×21+a×20=A(二进制数转换为十进制数的过程)
假设该数未转换为二进制数,除以基数2得:
A/2=e×24/2+d×23/2+c×22/2+b×21/2+a×20/2
注意:a的值为0或1,不能被2整除,因此余下;其他的各项均能被2整除,因为它们都包含因数2。除以2后得到的商为:
e×23+d×22+c×21+b×20
再除以基数2余下了b,依此类推。当这个数不能再被2除时,最先余的a在低位,而后来的余数依次在高位,所以要把所有的余数按照逆序排列,正好是edcba。
十进制小数转换成二进制小数采用“乘2取整,顺序排列”法。具体做法是:用2乘以十进制小数,可以得到积,将积的整数部分取出,再用2乘以余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到乘积中的小数部分为零,然后把取出的整数部分按顺序排列,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。例如,将(0.625)10转换为二进制得(0.101)2。
0.625×2=1.25--------------取出整数部分1(高位)
0.25×2=0.5---------------取出整数部分0
0.5×2=1----------------取出整数部分1(低位)
假设一个十进制小数B转换为二进制小数0.ab的形式,同样按权展开,得:
B=a×2-1+b×2-2
因为小数部分的位权是负次幂,所以只能乘2,得:
2×B=a+b×2-1
注意:a变成了整数部分,我们取整数正好是取到了a,剩下的小数部分依此类推。小数部分的按权展开的数位顺序正好和整数部分相反,所以不必反向排列。
3.二进制数与十六进制数相互转换
二进制和十六进制的互相转换比较重要,因为在程序中经常把二进制数写为十六进制的形式,从而容易阅读。不过这二者的转换却不用计算,每位程序员都应当能将二进制数直接转换为十六进制数,反之亦然。
十六进制有16个数,即0~15,用二进制表示15就是1111,从而可以推断出,16个数用二进制可以表示成0000~1111,顾名思义,也就是每四个二进制位为一个十六进制数。
(0111101)2可以这样分组:0011|1101(从右往左,每4位为一组,最高位不足4位可用0补齐),把每一组(4位)二进制数转换为十进制数,然后再写成对应十六进制数的形式。0111101就可以换算成十六进制的(3D)16。
如果是带有小数的二进制数,则小数部分从左往右每4位为一组,不足4位低位用0补齐。然后每一组(4位)二进制数转换为十进制数,然后再写为十六进制数的形式,组成十六进制数的小数部分。
反之,如何迅速将十六进制数转换为二进制数呢?把每1位十六进制数转换为4位二进制数即可。例如十六进制数FD转换为二进制数,先转换F,它是十进制的15,然后15再转换为二进制数。这里不使用“除2取余”的方法,直接使用四位二进制数各位的权值8421去凑。F=8+4+2+1,所以四位全为1,即二进制数为1111。接着转换D,它的十进制数是13,13=8+4+1,没有权值2,则二进制数的第二位为0,即二进制数为1101。所以,(FD)16转换为二进制数为(11111101)2。
4.二进制数与八进制数相互转换
二进制数转换为八进制数的方法与二进制数转换为十六进制数的方法相似。因为八进制数有0~7八个数字,可用二进制表示为000~111,也就是每三个二进制位为一个八进制位。则二进制数整数部分从右往左每三位为一组(不足三位高位用0补齐),转换为十进制数,则得到转换后的八进制数。二进制小数部分则按照从左到右的顺序每三位分为一组(不足三位低位用0补齐),转换为十进制数。例如(11001.101)2=(011001.101)2=(31.5)8