其实,除了我们常用的十进制数和电脑用的二进制数之外,生活中还有很多的计数进
制,并且有很多的进制也在电脑中使用。
1.4.1 神奇的八卦:八进制
八卦最初是上古人们记事的符号,后被用为 卜筮符号,古代常用八卦图作为除凶避灾 的吉祥图案。因此,八卦也就被打上了封建迷信的标记。
1 .从八卦说起
其实,八卦中隐含了二进制和八进制的概念。首先,八卦的最基本概念是阴和阳,这 就相当于二进制中的0和1 。在八卦图中用一根长实线代表阳,用一根中间断开的线代表 阴,然后由3个这样的线条符号组成8种形式 (相当于3位二进制数,可以表示8种状态) , 因此叫做八卦,如图1-34所示。
图1-34
在八卦中,每一卦形代表一定的事物。乾代表天、坤代表地、坎代表水、离代表火、 震代表雷、艮 (gèn) 代表山、巽 (xùn) 代表风、兑代表泽。
经过几千年的发展,八卦被赋予了很多的含义,除了上面介绍的代表自然现象之外, 还可以代表方位、家族、五行,还可以将卦图转换为二进制数。如表1-2所示就是八卦中 各卦所代表的不同含义。
表1-2 八卦的含义
2 .一种计算方式:八进制
可以看出,八卦中的每一卦由3位二进制组成,这样表示8种状态的数据就是一种八进 制计数方法。当然,八进制计数不会使用八卦的方式来表示,更多的情况下是使用阿拉伯 数字来表示。
八进制计数法则主要有以下3个特点:
基数为8;
由8个数码组成,分别是0 、1 、2 、3 、4 、5 、6 、7;
逢8进1 ,借1当8。
如表1-3所示是十进制数、八进制数和二进制数的对应关系。
表1-3 十进制数、八进制数、二进制数对应关系
续表
从表1-3中可看出,1位八进制数与3位二进制数相对应。
八进制计数法在早期的计算机系统中很常见,因此,偶尔我们还能看到人们使用八进 制表示法。八进制适用于12位和36位计算机系统 (或者其他位数为3的倍数的计算机系 统) 。但是,对于位数为2的幂 (8位、16位、32位与64位计算机系统) 的计算机系统来 说,八进制就不算很好了。因此,在过去几十年里,八进制渐渐地淡出了电脑。不过,还 是有一些程序设计语言提供了使用八进制符号来表示数字的能力,而且还是有一些比较古 老的UNIX应用仍在使用八进制。
1.4.2 钟表使用的十二进制
另一个我们常用的进制就是十二进制,如图1-35所示的钟表表面显示为12个小时,即 每12小时绕一圈,又从0点开始。
图1-35
历史上,在很多古老文明中都使用十二进制来记数。这或许是由于一年中月球绕地球 转12圈。在中国文化中,十二进制在记时中也有广泛应用。中国古代设有12地支,与一天 的12个时辰对应。一个地支还对应2个节气,从而表示1年的24节气。同时,将地支与12种 动物对应,成为12生肖,表示12年为周期的循环。
十二进制在各种度量衡中也经常会用到。如英制单位中1英尺等于12英寸,金衡制中1 金衡磅等于12金衡盎司。
十二进制计数法的规则如下:
基数为12;
由12个数码组成,分别是0 、1 、2 、3 、4 、5 、6 、7 、8 、9 、A 、B;
逢12进1 ,借1当12。
虽然十二进制在日常生活中很常用,不过,在计算机程序设计中使用的频率倒不多, 反而是二进制、八进制、十进制、十六进制使用得要多一些。
1.4.3 半斤八两:十六进制
再来看一个计算机中使用得很多的进制:十六进制。
在日常生活中,也有很多使用十六进制的地方。中国原来使用的重量单位就是十六进 制的,即16两为1斤,这也就有了所谓的“半斤八两”的说法了。
现在还在使用的磅和盎司这两个重量单位也是采用十六进制的方式计数的,1磅等于 16盎司。
计算机中使用二进制可以很好地计数和运算,为什么还要使用十六进制呢?
在使用二进制书写程序时,会发现有一个很麻烦的问题,要用二进制数表示一个比较 大的十进制数时会需要很多位的二进制位。例如,表示十进制的255 ,就需要8位二进制 数,而表示65535这个十进制数,则需要16位二进制数。
在程序中要处理的数据经常会比65535大得多,那就需要使用二进制数的更多位数 了。对于很多位的二进制数,不但书写困难,还容易出错 (这么长一串,稍不注意就可能 输入错误) 。
而使用十进制数又不方便与二进制数相对应,因此就引进了十六进制。
十六进制计数法的规则如下:
基数为16;
由16个数码组成,分别是0 、1 、2 、3 、4 、5 、6 、7 、8 、9 、A 、B 、C 、D 、E 、F; 逢16进1 ,借1当16。
如表1-4所示是十进制数、十六进制数和二进制数的对应关系。
表1-4 十进制数、十六进制数、二进制数对应关系
续表
从表1-4中可看出,1位十六进制数与4位二进制数相对应。这样,当程序员在编写程 序时,若将数据按十六进制格式书写,将大大缩短输入数据的位数。例如,对于十进制数 255 ,用二进制表示需要8个1来表达 (即1111 1111) ,而用十六进制来表示,则只需要2 个F (即FF) 。类似地,对于十进制数65535用二进制来表示需要16位,而用十六进制来 表示,则只需要4位。
1.4.4 60年一个甲子:六十进制
在中国,经常可以听到“甲子”这个概念,这是农历历法中的一个概念,每60年为一个
甲子,以天干与地支两者经一定的组合方式搭配成60对,为一个周期。
这就是六十进制的一种使用。
在现实生活中,使用六十进制的地方也很多。不过,与其他进位制不同,六十进制在 一般运算和逻辑中并不常用,主要用于计算角度、地理坐标和时间。
例如,1小时等于60分钟,而1分钟则为60秒。而1个圆可被均分成360度,每1度有60 角分,1角分等于60角秒。
六十进制在计算机程序中使用得很少。
1.4.5 各种进制之间的转换
前面介绍二进制时,曾介绍了二进制数与十进制数之间的转换方法:二进制数转换为 十进制数时,将二进制数“按权展开” ,即可得到十进制数;而十进制数转换为二进制数 时,使用“除2取余,逆序排列”即可。
类似地,其他进制的数转换为十进制数时也可采用相似的方法,只是在“按权展 开”时,使用各进制的基数即可。因此,可得到其他进制转换为十进制的统一按权展开 式:
在上面的统一算式中,D表示转换后得到的十进制数,Xn-1为B进制中从右向左数第 n位数。例如,二进制数1101的按权展开式为:
而十六进制BC0D的按权展开式为:
如果要将十进制数转换为B进制数,也可以采用除以基数B再取余的方法来求得,如 图1-33所示,只是将除数由2改为B进制数的基数B即可。
只要能将任意数转换为十进制数,然后又有将十进制数转换为任意进制数的方法,通 过十进制数进行中转,即可进行任意进制数之间的转换了。使用这种思路可编写出以下的
进制转换程序,可在任意两种进制之间进行转换。
这个程序比较简单,定义了4个函数:
main()函数为主函数,接收输入源数据、进制,以及需要转换成的进制。 int_pow()函数为幂运算函数。在任意进制数按权展开时需要用到幂运算。 xtod()函数为将任意进制转换为十进制的函数,通过按权展开的方式进行。 dtox()函数为将十进制数转换为任意进制的函数,通过除模取余的方法进行。
编译运行以上程序,输入一个数据及其进制,然后输入要转换到的进制,即可得到结 果。如图1-36所示,当输入BC0D ,并输入进制为16 ,转换的进制为10 ,则可得到48141。
图1-36
1.4.6 二进制与八进制、十六进制的转换
除了按以上方法进行任意进制之间的转换外,在程序中经常用到的是二进制与八进 制、二进制与十六进制之间的转换。对于这些特殊进制间的转换,可以用更简单的方法。
二进制数转换为八进制数,可概括为“3位并1位”的方法。具体转换方法是:按从右向 左的方向,每3位二进制数为一组,最高位不足3位时,添0补足3位,然后将各组的3位二 进制数按22 、21 、20权展开后相加,得到一位八进制数。例如:
而将八进制数转换为二进制数时,可采用相反的操作,即将每位八进制数拆为3位二 进制数,称为“1位拆3位”。
类似地,由于1位十六进制数与4位二进制数对应,二进制数转换为十六进制数时就可 按“4位并1位”的方法进行,而十六进制数转换为二进制数则可按“1位拆4位”的方法进行。
第2章 神奇的素数
素数在自然数中占有非常重要的地位,素数是一类既简单又神秘的数字。说其简单, 是因为小学生也知道什么是素数;说其神秘,是因为从古至今,多少数学家都想弄明白素 数的规则,却一直没有找到其分布规律。
数学家都没研究出来的规律,程序员当然也不可能会找到。但是,任何事物都有正反 两面,正是由于素数的无规律特点,在密码学中就可以大量采用。另外,在一些齿轮啮合 设计中,也通常将齿轮的齿数设计成素数,以增加两齿轮中两个相同的齿相遇啮合次数的 最小公倍数,这样可增强齿轮的耐用度,减少故障。