罗国明 钟晴江
摘要: 程序设计是一门逻辑性很强的课程,教会学生编程关键是教会学生编程的思想,以及分析、解决问题的方法。很多程序的编程思想都有类似之处。文章利用归纳法的思想,把进制转换归纳成具有共性的问题进行归类,设计了把2、8、16进制统一转换为10进制的算法;同样设计了把10进制转换为2、8、16进制的统一算法。把这种归纳法的思想应用于教学,取得了良好的教学效果。
关键词: 程序设计; 归类; 进制转换
中图分类号:TP3-05文献标志码:A文章编号:1006-8228(2012)05-45-02
Digital conversion algorithm research based on classified teaching
Luo Guoming, Zhong Qingjiang
(Zhejiang University, Information Management Department of City College, Hangzhou, Zhejiang 310015, China)
Abstract: "Programming" is a strong logical course. how to teach students programming? The key is to teach students programming ideas, how to analyze problems and solve the problem. A lot of programming methods are similar. Using inductive method, with common problems grouped into a classified, the algorithm of transfering binary, octal, hexadecimal into decimal, decimal into a unified binary, octal, hexadecimal is developed, This same idea can be easily extended to other similar programming, and the idea of this inductive method used in teaching, has been a good teaching results obtained.
Key words: programming; classified; digital conversion
0 引言
程序设计是一门非计算机专业的公共基础课。随着对程序设计教学手段和教学方法研究和探讨的不断深入,我们的教学方法也在不断地推进,并从平时的教学实践中总结出很多适应现代大学生的教学方法和手段。程序设计课程除了要教会学生如何思考问题、分析问题、解决问题,还必须教会学生一些程序设计的关键算法,教会学生能从问题中分析并提取关键因素,然后把具有共同特性的一类问题归结为一个算法。本文以进制转换的算法为例,从教学的角度探讨了进制转换算法的归类实现思想[1]。由于篇幅关系,我们只讨论整数部分的进制转换。
1 把2、8、16进制转化为10进制的统一算法
我们用进位计数制来说明2、8、16进制转化为10进制的方法。
进位计数制是人们利用符号来计数的一种方法。进位计数制使用了一组数码符号、基数和位权[2]。
⑴ 数码:用不同的数字符号来表示一种数制的数值,这些数字符号称为“数码”。
⑵ 基数:进位计数制的每位数上可能有的数码个数称为“基数”。
⑶ 位权:在一个数中,同一个数码处于不同位置则表示不同的值,把基数的某次幂称为“位权”。
按照数码、基数和位权,如果把(11111)2转化为十进制,可以写成以下公式:
(11111)2=1*24+1*23+1*22+1*21+1*20=(15)10
从该公式不难归纳得到以下的2进制转化为10进制的公式:
(B)2=Bn*2n-1+Bn-1*2n-2+···+B2*21+B1*20
从该式同样可得到以下8、16进制转换为10进制的公式:
(O)8=On*8n-1+On-1*8n-2+···+O2*81+O1*80
(H)16=Hn*16n-1+Hn-1*16n-2+···+H2*161+H1*160
同样,从以上公式我们容易归纳出二、八、十六制转化为十进制的统一的表示方法:
(K)R=Kn*Rn-1+Kn-1*Rn-2+···+K2*R1+K1*R0
也可以写成以下的形式:
其中R表示进制基数,K表示数码,Ri-1中的i-1表示位权。例如:(12345)10=1*104+2*103+3*102+4*101+5*100
为了把算法写成有规律的循环,可把上式写成以下的形式,例如:利用上面通项公式把12345的10进制数转换为8进制数,可以用以下公式表示:
n=(12345)10=((((y+1)*8+2)*8+3)*8+4)*8+5=(30071)8
可以把上式归纳写成程序的循环的形式如下:
result=0;
for(i=0;num[i]!=' ';i++)
result=result*base+num[i]-'0';
其中base表示8进制,如果把base用2、8、16中任何一个数表示,那么利用上式的程序,只要num[i]是10以内的数,就都可以把2、8、16进制转化为10进制数了。
因为16进制数有非数字的字符A-F或a-f,将程序算法稍作变化就可以处理16进制:把num[i]-'0'用num[i]-'A'-'7'代替大写字母,或者num[i]-'a'-87代替小写字母,这样处理的目的是算出16进制中10~15的值。
为了把大小写字符统一计算,如果遇到小写字符先把小写字符转化为大写字符,即if(num[i]>='a'&&num[i]<='f') num[i]=num[i]-32;那么大小写字母就可统一处理了。
根据以上的编程思想,二、八、十六进制数转化为十进制数的函数代码如下:
int Convert_2_8_16to10(int base,char num[])
//把2、8、16进制转换为10进制
{//其中base为2、8、16基数,num[]为存放2、8、16进制数的数码
int i, decimal=0;
for(i=0;num[i]!=' ';i++) { //如果num[i]!=' '转换处理结束
if(num[i]<='9') //判别是否0~9之间的数字
decimal=decimal*base+num[i]-'0'; //0~9之间的数码处理公式
else {
if(num[i]>='a'&&num[i]<='f') //判别是否a~f之间的小写字母
num[i]=num[i]-32; //把小写字符转换成大写字符
decimal=decimal*base+num[i]-'7'; //A~F之间的数码处理公式
}
}
return decimal;
}
以上的例子可以拓展到很多的相关情况,如:把一个整数逆序排列,123456转化为654321,就可以写成
n=123456->654321
((y+3)*10+2)*10+1
((y+n%10)*10+n/10%10)*10+n/100%10
程序写成
y=0;
while(n) {
y=y*10+n%10;
n=n/10;
}
如果是a+aa+aaa+aaaa,a代表1-9之间的一个数字,同样也可以写成
(((y+a)*10+a)*10+a)*10+a
程序写成
y=0;
for(i=1; i<=n; i++) {
y=y*10+a;
s=s+y;
}
如果是字符789转换为整数789,程序也可以写成
y=0;
while((ch=getchar())!=‘ )
y=y*10+(ch-'0');
有很多相同的实例,他们都有一个共同的通项公式
y=y*10+x; x可以是n%10、a或(ch-'0')
以上这些程序都可以归成一类,这样,学生学习起来也比较容易理解[3]。
2 10进制转化为2、8、16进制的统一算法
10进制转化为2、8、16进制的基本方法是:将整数部分除以base,余数为该位权上的数,而商继续除以base,余数又为上一个位权上的数,这个步骤一直持续下去,直到商为0为止。最后读数时候,从最后一个余数读起,一直到最前面的一个余数。其中base为2、8、16中的一个数[4]。
先举一个例子,把269转化为2进制数,即把269除2,所得余数即为2进制数的个位数上的数码,再将商除以2,余数为2进制十位数上的数码,如此反复,直到商小于2为止,最后得(269)10=(100001101)2。
10进制转化为8进制和16进制方法也和上面一样。通过上面的例子可以归纳出下面的通项公式。
num[i]='0'+n%base;
其中:base是2、8或16进制中0~9的数。
但是上面的的通项公式只能处理余数小于10的数,如果余数大于等于10,那么就要用以下的通项公式处理。
num[i]='A'+n%base-10;
其中:base是16。
根据以上的编程思想,十进制数转换为二、八、十六进制数函数的代码如下:
int Convert_10to2_8_16(int n,int base,char num[])
//把10进制转换为2、8、16进制
{//n为十进制数码,base为2、8、16进制的其中一个,
num[]为存放转换的字符
int i=0; //定义i为数组下标
do { //进制转换开始
if(n%base>9) //十六进制
num[i]='A'+n%base-10; //处理A~F中的一个字符
else
num[i]='0'+n%base; //处理0~9中的一个字符
n=n/base; //取数码除base的整数部分
i++; //为下一个数组作准备
} while(n!=0); //n不等于0,继续处理数码
return i; //返回转换后数组字符的个数
} //处理后的结果放在数组中
以上十进制转化为二、八、十六进制的程序,很容易推广到十进制到其他进制的转换[5]。
3 结束语
虽然上面的算法用C语言编写,但对于其他程序设计类语言也可采用同样的教学方法,相信一定会收到比较满意的效果。其实掌握了以上的编程方法,任意进制的编程转换都非常容易实现。
授人以鱼,不如授人以渔。教会学生程序设计归类的思想,实际上是教会学生分析问题和解决问题的方法。日常生活中对很多问题编程的方法都差不多,怎样把这些问题有机地联系起来,这在教学中非常重要。教师如何教会学生思考问题、分析问题、解决问题是教学改革中的一个重要环节。教师教会学生程序设计并不难,但要教会学生思考问题的方法却不容易。当学生掌握了程序设计的思考方法,以后有问题就可以自己解决。实际上这种教学方法提高了学习者分析和解决类似问题的能力。程序设计归类问题就是一种重要的思考方法。
参考文献:
[1] 刘均,李人厚,郑庆华.一种基于进制转换的数值型关联规则分析方
法[J].计算机工程,2005.31(9):17~18,33
[2] 赵建强.用多位数动态数组实现进制转换的研究[J].湖南文理学院学
报(自然科学版),2011.23(1):71~73
[3] 田祖伟,孙光,杨素萍.进制转换的快速方法及应用[J].电脑编程技巧
与维护,2008.17:28~29
[4] 刘建波,蔡文水,吕铁山.十进制与任意进制转换的设计与实现[J].计
算机系统应用,2003.10:69~71
[5] 胡雪丹,管玉玲,张晶.一种将十进制数转换成R进制数的新算法
[J]. 电脑知识与技术,2010.13:3477~3478