这是一个C语言示例:输入一个 M 进制的整数 x,实现对 x 向任意非 M 进制的数的转换。
掌握不同数制之间的转换关系是解决该问题的关键:
从各种数制转换方法可以看出,数制间转换时都是以各个数位上的数字参加某种运算的。因而,我们设计一个数组 temp[ ] 用来存放转换前后的数,则这个数各位上的数字分别就是一个数组元素。比如,将十六进制数“25D”存入 temp[ ] 数组后,temp[0] 的值为字符'2',temp[1] 的值为字符'5',temp[2] 的值为字符'D'。
但是,在数制转换中参与运算的各数位上的数字其类型都是整型而非字符型,因而,我们还需要设计两个函数,一个用于将字符转换成数字,另一个用于将数字转换为字符。
在该问题中,字符转换为对应的数字分两类情况考虑:
int char_to_num(char ch) //自定义函数:返回字符对应的数字
{
if(ch>='0'&&ch<='9')
return ch-'0'; //将数字字符转换成数字
else
return ch-'A'+10; //将字母字符转换成数字
}
同理,数字转换为对应的字符也分两种情况:
char num_to_char(int num) //自定义函数:返回数字对应的字符
{
if(num>=0&&num<=9)
return (char)('0'+num-0); //将 0~9 转换成字符
else
return (char)('A'+num-10) //将 10~15 转换成字符
}
其他数值转换成十进制采用按权展开相加的方法,因此我们定义一个变量 decimal_num 来存储相加的和,同时定义一个变量 decimal_s 来计算并存储各位上的权值。以下为其他数值转换为十进制数的自定义函数代码:
long source_to_decimal(char temp[],int source)
{
long decimal_num=0; //存储按权展开累加所得的和(即十进制数)
long decimal_s; //存储个位上的权值
int i, j, length;
for(i=0;temp[i]!='\0';i++); //计算有效字符个数
length = i;
for(i=0;i<length-1;i++)
{
decimal_s=1;
for(j=1;j<=length-i-1;j++) //计算各位上的权值
decimal_s *= source;
decimal_num += decimal_s*char_to_num(temp[i]); //累加
}
return decimal_num; //返回由其他数制转换成的十进制数
}
以上代码中使用了双重 for 循环语句,程序运行效率不高。其实我们可以将各位权值的计算过程合并在展开累加这层循环当中,这样就可以减少一层 for 循环,提高程序运行效率。优化以后的函数代码如下:
long source_to_decimal(char temp[ ],int source)
{
long decimal_num=0; //存储展开之后的和
int i, j;
for(i=0;temp[i]!='\0';i++); //计算数组中有效字符数
for(j=0; j<=i-1; j++) //累加
decimal_num=(decimal_num*source)+char_to_num(temp[j]);
return decimal_num; //返回由其他数制转换成的十进制数
}
上面的代码中 decimal_num 在每次累加时先要乘一次基数,这样累加 n 次将所有的有效元素都转换累加后,第一个元素 temp[0] 与基数相乘了 n-1 次,即基数的 n-1 次方,刚好是其权值,第二个元素 temp[1] 与基数相乘了 n-2 次,即基数的 n-2 次方,也刚好是其权值,……最后一个元素 temp[n-1] 与基数相乘了 0 次,即基数的 0 次方,也是其权值 1。
十进制转换成其他数制采用除以基数取余的方法。以十进制转化为八进制为例:
十进制转换成其他数制并打印转换后的新数的自定义函数代码如下:
void decimal_to_obj(char temp[ ],long decimal_num,int object)
{
int i=0;
while(decimal_num)
{
temp[i]=num_to_char(decimal_num%object); //求余数并转为字符
decimal_num=decimal_num/object; //用十进制数除以基数
i++;
}
temp[i]='\0';
int j;
for(j=i-1;j>=0;j--) //倒序输出temp数组(由十进制数转换成的新数)
printf("%c",temp[j]);
printf("\n");
}
代码清单 1:数制转换
#include <stdio.h>
#include <stdlib.h>
#define MAXCHAR 101 /*最大允许字符串长度*/
int char_to_num(char ch)
{
if(ch>='0'&&ch<='9')
return ch-'0'; /*将数字字符转换成数字*/
else
return ch-'A'+10; /*将字母字符转换成数字*/
}
char num_to_char(int num)
{
if(num>=0&&num<=9)
return (char)('0'+num-0); /*将0~9之间的数字转换成字符*/
else
return (char)('A'+num-10); /*将大于10的数字转换成字符*/
}
long source_to_decimal(char temp[],int source)
{
long decimal_num=0; /*存储展开之后的和*/
int length;
int i;
for(i=0;temp[i]!='\0';i++);
length=i;
for(i=0;i<=length-1;i++) /*累加*/
decimal_num=(decimal_num*source)+char_to_num(temp[i]);
return decimal_num;
}
void decimal_to_object(char temp[],long decimal_num,int object)
{
int i=0;
while(decimal_num)
{
temp[i]=num_to_char(decimal_num%object); /*求出余数并转换为字符*/
decimal_num=decimal_num/object; /*用十进制数除以基数*/
i++;
}
temp[i]='\0';
int j;
for(j=i-1;j>=0;j--) /*输出temp数组中的值*/
printf("%c",temp[j]);
printf("\n");
}
int main()
{
int source; /*存储原数制*/
int object; /*存储目标数制*/
int length; /*存储转换成目标数制后字符数组的长度*/
long decimal_num; /*存储转换成的10进制数*/
char temp[MAXCHAR]; /*存储待转换的数值和转换后的数值*/
int flag=1; /*存储是否退出程序的标志*/
while(flag) /*利用输入的flag值控制循环是否结束*/
{
printf("转换前的数是:"); scanf("%s",temp);
printf("转换前的数制是:"); scanf("%d",&source);
printf("转换后的数制是:"); scanf("%d",&object);
printf("转换后的数是:");
decimal_num = source_to_decimal(temp,source);
decimal_to_object(temp,decimal_num,object);
printf("\n继续请输入1,否则输入0:\n");
scanf("%d",&flag);
}
system("pause");
return 0;
}
运行结果为:
转换前的数是:17
转换前的数制是:10
转换后的数制是:2
转换后的数是:10001
继续请输入1,否则输入0:
1
转换前的数是:AF7
转换前的数制是:16
转换后的数制是:10
转换后的数是:2807
继续请输入1,否则输入0:
1
转换前的数是:653
转换前的数制是:8
转换后的数制是:16
转换后的数是:1AB
继续请输入1,否则输入0:
1
转换前的数是:100010011100
转换前的数制是:2
转换后的数制是:8
转换后的数是:4234
继续请输入1,否则输入0:
0