最近受网友的邀请,就写一篇入门的教学文章。不过对于已经有一定实力水平的人来说,入门级的东西反而对于他(她)们来说不容易解释清楚,我也想挑战一下自己,看看我能把一些基础问题怎么解释能让智商80的人也能看明白(虽然这样说有点夸张),所以文章的标题就叫做“傻瓜学习C语言进制转换”,不过也不是没有要求的,要求是,看本文的时候,请你一定要按顺序看,并且要确定你会写这样一个c程序:输入一个int,分解出它的个位,十位,百位(提示:要用’%'求模运算和’/'整除运算)。。。。。。
1.数值与进制
数值与进制是两个不同的东西。数值是什么?100,200这种并不是数值。
什么是数值?古代的时候,人们记数,有一个物品就记一块石头,或者有11个物品,就打11个绳结,这就是数值,如果你要表示1000,那你还真的需要打1000个绳结来表示。可问题就是,这样子你会累死,为了不用累死,于是他们发明了另一种表达方式:准备两种不同的石头A和B,有一个,那就用一块A石头表示,两个就用两块A表示,如果太多了,比如10个,就用一块B石头来表示有10个A石头,比如AAAAABB表示25个。但是,如果表达的数值更大,那就再多准备一种石头C,每10个B石头就用一个C石头来表示,比如AABCC表示212。于是,这样就可以大大减少所需要的石头的数目,而这,就是进制。
进制是数值的一种表示方式
2.数值与进制的转化
进制是为了表示一个数值,如果是每10个进一,那么就是我们熟悉的10进制,否则,如果是每k个进一,那就是k进制,比如我们的时间,是每60秒记1分钟,这就是60进制。然后,怎么把一个用特定进制的表示,得到它的数值呢?很简单,比如上文说的AABCC,首先,有两个A,分解得AA + BCC,就是2 + BBC,然后,1个B就是10个A,于是就是AA + AAAAAAAAAA + AAAAAAAAAA + C,然后一个C等于10个B,就是AA + AAAAAAAAAA + AAAAAAAAAA + BBBBBBBBBB,这样一直拆下去,直到全部是A为止,你就得到实际的数值了,实际的数值就是A的个数,记住这一点,数值和进制是两码事。
然后,反过来,怎么把一个数值转化为特定进制呢?很简单,按照进制的定义,比如现在有数值AAAAAAAAAAAAAAAAAAAAAAA,然后,要转成10进制,那么我们每10个分一分组:AAAAAAAAAA + AAAAAAAAAA + AAA,然后,把10个A用B来表示,得到:B + B + AAA,如果B有10个,那再把它换成C表示。那么,如果你明白了以上方法,你就得到一个最基本的进制转换手段,就是先化为数值,再重新用另一个进制表示。比如10进制的13,要化成二进制,那么,就是BAAA -> AAAAAAAAAAA -> AA AA AA AA AA AA A 这时,换一个符号,每两个A用一个M表示,那么就是MM MM MM A,再每两个M用一个N表示,得到NN N A,再每两个N用一个P表示,得到P N A。而在这里,一个P等于8个A,一个N等于4个A,所以P + N + A你可以验算出8 + 4 + 1,等于原来的数值。而这种表示方法,就和罗马数字很相似,罗马数字里,用I表示1,用V表示5,用X表示10,于是18就用XVIII表达,用一个字母多次重复来表达一个数值。
后来,为了能更方便书写,因为字母数量是有限的,无法表达更大的数字,书写方式改用阿拉伯数字写在不同的位置来表达,于是就是我们今天的10进制数字。比如刚刚的例子,BAAA,有一个B,于是在十位写1,然后有三个B,在个位写3,也就是B的个数,组合起来就是13,这是十进制的情况。如果是二进制,刚刚我们得到的结果是PNA,注意这里没有M,相当于0个,而如果我们用二进制写,那就有四个位,个位有一个A,记1,第二位相当于M的个数,是0,组合起来是01,第三位是N,记1,组合是101,第四位有一个P,再组合就是1101,于是这就是10进制的13,化为二进制的结果。
3.进制的特点
问你,3638除以10的余数是多少?给你一秒种思考时间,多少?如果这个你不能马上说出来,那你就要反省了。结果应该是8,直接看个位不就对了。那么3638除以10的商呢?再给你一秒。。。。。。。。。。。。。。。。。。。这个答错的话要重读小学了,答案当然是363.8,如果把这个数取整,不要小数部分,那就是363。小学的时候你就应该知道,对一个数乘以10或者除以10这种计算是超简单的,因为我们用的是10进制。类似的,问一下你,经过60个5秒是多少分钟多少秒?再给你一秒思考时间,要毫不犹豫的回答我。你可别去计算60*5=300,这是多余的。答案是5分钟,时间我们用的60进制,那么乘以60只要改一下单位就足够了,肯定是对的。再问你,10分钟分成60份是多少秒?你必须立即回答我是10秒。
我们推广到任意k进制,按这个特点,k进制下,乘以k或者除以k的运算是超级简单的,比如8进制的123,乘以8肯定是1230,除以8就是12.3,相当于在移动小数点而已。于是,k进制下乘除k就是移动小数点。而除以k求余数的话,像刚刚的8进制的123除以8,就等于12余3,就是要得到个位上的数字,同时得到原来的数舍弃掉个位的结果。这个性质非常的重要!除法的本质是什么?其实除以k是得到被除数在k进制下的个位数(余数),和小数点左移的结果(商)。
4. C下实现数值转化为进制
好,现在回到程序,给你一个int n,要把它的各位上的数字取出来,按上面的性质,那就很简单了,先得到个位,n%10(这个’%'是求余运算),然后小数点左移,n = n / 10; 然后不断循环这个过程,如下代码:
int n = 2456;
while (n > 0)
{
printf("%d,", n % 10);
n = n / 10;
}
输出结果是”6,5,4,2,”,好好领悟一下这段代码。给你五分钟时间。每一次%10就是取出个位,每一次/10就是丢掉个位。
而如果把输出的结果里的数字,逆过来看,就是”2456″。
在这里,那个int所表示的,就是一个数值,刚刚我们的代码所做的事就是把这个数值,一位一位的分解出来。
而事实上,这个过程就是把数值转化为特定进制的过程。刚刚就是把数值转化为10进制。
如果把刚刚的代码改为:
int n = 13;
while (n > 0)
{
printf("%d,", n % 2);
n = n / 2;
}
没错,输出结果是”1,0,1,1″,就是刚刚把13化为二进制的例子,每一次%2就是取出二进制下的个位,每一次/2就是丢掉二进制下的个位。
只要把那个次序反过来,就得到1101,就是13化为二进制的结果。在你真正搞明白了除法的本质后,那么,数值转化为以k进制表示那是一件很简单的事。
5. 进制转化为数值
这部分我不打算讲,很多人对这个比起前面的内容来说容易理解很多,直接用进制的定义就已经很好办了,没什么太难理解的东西。
6. 作业
编写一个程序,输入三个整数n A B,表示把A进制的n,转换为B进制,并输出。
样例:
输入 输出
11 8 10 9
129 10 2 10000001
22 3 6 12
假定输入的A和B都在2-10这个范围,超出范围的不用去处理,输入的n保证在int范围内。