进制转换

所谓进制转换,就是将一种进制的数字转换为另一种进制的数字。数字的表示形式虽然改变了,但是数字的值并没有变。

这里我们讲解两种方法,第一种是简单的口算法,第二种是复杂的公式法。

进制转换口算法

我们来思考一个问题:为什么八进制数 17 对应的十进制数是 15?我们看八进制数 17 中的 7,这个 7 是没有进位的,它同十进制数 7 是一样的,因为它是在个位。而八进制数 17 中的 1,它能进一是因为有 8 才进一的,所以这个 1 代表的就是十进制的 8。所以一个 8 和一个 7 加起来就是 15,这就是为什么八进制数 17 对应的十进制数是 15 的原因。

现在我来考考读者,看读者能不能立刻回答出来。八进制数 23 对应的十进制数是多少?十进制数 34 对应的八进制数是多少?

同样,八进制数 23 中的 3 和十进制数 3 是一样的,而 2 说明进了两次位,有 8 才能进一次,进了两次说明是十进制的 16,所以 16 和 3 加起来就是 19。因此八进制数 23 对应的就是十进制数 19。

十进制数 34 里有 4 个 8,余 2,所以十进制数 34 对应的就是八进制的 42。

我再来问问大家,看大家能不能举一反三:十六进制的 3D 对应的十进制是多少?十进制的 83 对应的十六进制是多少?

方法是相同的,十六进制数 3D 中的 D 表示的是十进制的 13,而十六进制达到 16 才能进一次,数字 3 说明进了 3 次,即 48,13 和 48 加起来就是 61。因此,十六进制数 3D 就对应十进制数 61。同样,十进制 83 中有 5 个 16,余 3,所以十进制数 83 就是十六进制数 53。

如果是八进制和十六进制相互转换的话,因为它们都跟十进制有关系,所以可以将十进制当作一个桥梁,先转换成十进制,然后再转换成另一个进制。

以上的口算方法实际上就是进制转换的本质和奥秘的总结。但是用口算方法只能计算比较小的数字,当数字比较大的时候还是得在纸上算。之所以没有讲如何用口算进行二进制转换,原因就是二进制的计算量很大,不适合口算。介绍口算方法的主要目的是想让大家体会进制转换的本质,从而能够深刻理解下面所讲的公式法。

进制转换公式法

以上讲的是进制转换的本质,下面系统地讲一下进制转换。在阅读本节之前建议大家先掌握上节的内容,这样效率会更高,理解会更深刻。

1) r 进制转换成十进制

r 进制数 an an–1…a1 a对应的十进制数为:

an×r+ an–1×rn–1 + … + a1×r+ a0×r0

下面给大家举几个例子:
  • (1011011)2=1×26+0×25+1×24+1×23+0×22+1×21+1×20=64+0+16+8+0+2+1=91
  • (356)8=3×82+5×81+6×80=192+40+6=238
  • (2FB)16=2×162+15×161+11×160=512+240+11=763

2) 十进制转换成 r 进制

方法:除 r 取余数,直至商为零,余数倒序排序。

下面给大家举个例子:十进制 185 分别转换成二进制、八进制和十六进制。


所以(185)10=(10111001)2


所以(185)10=(271)8


(185)10=(B9)16

3) 进制之间的转换

上面讲了十进制和r进制之间的相互转换。可以说十进制是任意进制间相互转换的桥梁,任何进制都可以先转换成十进制,然后再转换成需要的进制。

但二进制和八进制、二进制和十六进制之间的相互转换可以直接计算。二进制的运算首先要记住窍门:8421。(1111)2=1×23+1×22+1×21+1×20=8+4+2+1,即二进制数 1111 从左到右每一位分别代表十进制的 8、4、2、1。

① 二进制转换为八进制

将二进制数从右到左,每三位组成一组,最左边不足三位的补零。然后对每组分别运用 8421 法则快速运算。如果二进制是 1 则保留,如果是 0 则舍去。比如:
  • (1111)2=8+4+2+1=15
  • (1010)2=8+0+2+0=10
  • (1100)2=8+4+0+0=12
  • (0101)2=0+4+0+1=5

所有的二进制转其他进制的运算都要记住这个法则。如果是二进制转十进制,且二进制数多于四位,那么其他位依次为 16、32、64、128……

只不过二进制转八进制时,因为是每三位为一组,所以就不存在第四位,这样 8 就都为 0 了,所以其实是 421 法则,但统一记为“8421”更顺口。

【练习】(11001011)2=(?)8

首先,从右到左分成三组,最左边不足三位的补零,即 011001011。然后对每组分别运用“8421”快速运算即 313。所以(11001011)2=(313)8

② 二进制转换为十六进制

将二进制数从右到左,每四位组成一组,最左边不足四位的补零。然后对每组分别运用“8421”法则快速运算。

【练习】(1011001011)2=(?)16

首先,从右到左分成四组,最左边不足四位的补零,即 001011001011。然后对每组分别运用“8421”法则快速运算即 2 C B。所以(11001011)2=(2CB)16

③ 八进制转换为二进制

对于每一位八进制数,分别运用“8421”法则快速运算,逐位展开成三位二进制数,不足三位的补零,最后最左边的零可省略。

【练习】(3754)8=(?)2

(3)8=(011)2,(7)8=(111)2,(5)8=(101)2,(4)8=(100)2,所以(3754)8=(11111101100)2

④ 十六进制转换为二进制

对于每一位十六进制数,分别运用“8421”法则快速运算,逐位展开成四位二进制数,不足四位的补零,最后最左边的零可省略。

【练习】(4B39F)16=(?)2

(4)16=(0100)2,(B)16=(1011)2,(3)16=(0011)2,(9)16=(1001)2,(F)16=(1111)2,所以(4B39F)16=(1001011001110011111)2

最后还有一个“小数部分的进制转换”,这个几乎用不到,所以就不讲了,要是以后用到了再看也不迟。

接下来给大家写一个程序。这个程序的功能是将同一个十进制数以不同的进制显示出来。这个程序大家暂时还看不懂,没关系,等学到后面再来看这个程序就很简单了。
#include <stdio.h>
int main(void){
    int i = 63;
    printf("i = %d\n", i);
    printf("i = %o\n", i);
    printf("i = %x\n", i);
    printf("i = %X\n", i);
    return 0;
}
运行结果:
i = 63
i = 77
i = 3f
i = 3F

其中:%d表示以十进制输出;%o表示以八进制输出,注意是字母 o 不是数字 0,而且一定是小写字母。这与前面讲的八进制数是数字 0 而不是字母 o 正好是相反的,千万不要弄混了。

%x%X表示以十六进制输出。那么它们有什么区别呢?如果是 %x 那么字母就是以小写的形式输出,如果是 %X 那么字母就是以大写的形式输出。这也是八进制中只有 %o 没有 %O 的原因,因为八进制中根本没有字母,所以不需要区分大小写。