本小节主要解决一个问题,对两种不同的进制,应该如何进行相互转换呢?
对于一个P进制数,如果要转换为Q进制,分为两步:
(1)将P进制数x转换为十进制数y
对于一个十进制数y=d1d2d3d4….dn,它可以写成以下形式:
y=d1*10^(n-1)+d2*10^(n-2)+d3*10^(n-3)+….+dn-1*10+dn
同样,如果P进制数x为a1a2a3….an,那么也可以写成以下形式来转换为十进制数y:
y=a1*P^(n-1)+a2*P^(n-2)+a3*P^(n-3)+….+an-1*P+dn
而这个公式很容易用循环进行实现:
int y=0,product=1;
while(x!=0){
y=y+(x%10)*product;
x=x/10;
product=product*P
}
(2)将十进制数y转换为Q进制数z
采用“除基取余法”进行转换。每次将待转换的数除以Q,然后将得到的余数作为低位存储,而商则继续除以Q并进行上面操作,最后当商为0时,将所有位从高到低输出就可以得到z。将十进制y转换为Q进制,结果存放于数组ans中,实现代码如下:
int z[40],size=0;
do{
ans[size++]=y%Q;
y=y/Q;
}while(y!=0);
问题 A: 又一版 A+B
时间限制: 1 Sec 内存限制: 32 MB
题目描述
输入两个不超过整型定义的非负10进制整数A和B(<=231-1),输出A+B的m (1 < m <10)进制数。
输入
输入格式:测试输入包含若干测试用例。每个测试用例占一行,给出m和A,B的值。
当m为0时输入结束。
输出
输出格式:每个测试用例的输出占一行,输出A+B的m进制数。
样例输入
2 4 5
8 123 456
0
样例输出
1001
1103
提示
注意输入的两个数相加后的结果可能会超过int和long的范围。
解题思路
这道题思路就是本小节学习的主要内容,上面有提到,在此就不赘述了。重点要注意输入的两个数相加后结果可能会超过int和long的范围,因此可以选择long long的范围,同时输入的两个数a、b也应该为长整型,但是在32位编译系统下,long和int所占空间是相同的。
Submission
#include <stdio.h>
int main()
{
int m,i;
long a,b;
int num;
long long sum;
int ans[1000]={0};
while(scanf("%d",&m)&&m!=0){
scanf("%lld%lld",&a,&b);
num=0;
sum=a+b;
do{
ans[num++]=sum%m;
sum=sum/m;
}while(sum!=0);
for(i=num-1;i>=0;i--){
printf("%d",ans[i]);
ans[i]=0;
}
printf("\n");
}
return 0;
}
问题 B: 数制转换
时间限制: 1 Sec 内存限制: 32 MB
题目描述
求任意两个不同进制非负整数的转换(2进制~16进制),所给整数在long所能表达的范围之内。
不同进制的表示符号为(0,1,…,9,a,b,…,f)或者(0,1,…,9,A,B,…,F)。
输入
输入只有一行,包含三个整数a,n,b。a表示其后的n 是a进制整数,b表示欲将a进制整数n转换成b进制整数。a,b是十进制整数,2 =< a,b <= 16。
输出
可能有多组测试数据,对于每组数据,输出包含一行,该行有一个整数为转换后的b进制数。输出时字母符号全部用大写表示,即(0,1,…,9,A,B,…,F)。
样例输入
4 123 10
样例输出
27
提示
用字符串存储和表示不同进制的数。
Submission
#include <stdio.h>
char str[100];
int a,b;
int num,product,i;
int main() {
while(scanf("%d%s %d", &a, str, &b) != EOF){
num = 0;
for(i=0; str[i]; i++){
if(str[i] >= 'a') str[i] -= 32;
product = (str[i] >= 'A' ? str[i]-'A'+10:str[i]-'0');
num = num * a + product;
}
int cnt=0;
if(num == 0)
{puts("0"); continue;}
while(num){
if(num%b <=9)
str[cnt++] = num%b+'0';
else
str[cnt++] = num%b-10+'A';
num = num/b;
}
for(i=cnt-1; i>=0; i--)
printf("%c",str[i]);
puts("");
}
return 0;
}
问题 C: 进制转换
时间限制: 1 Sec 内存限制: 32 MB
题目描述
将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。
输入
多组数据,每行为一个长度不超过30位的十进制非负整数。
(注意是10进制数字的个数可能有30个,而非30bits的整数)
输出
每行输出对应的二进制数。
样例输入
985
211
1126
样例输出
1111011001
11010011
10001100110
Submission
#include <stdio.h>
#include <string.h>
char a[31];
int main()
{
while(scanf("%s",a)!=EOF){
int i=0;
int sum=1;//每一轮除以2之后的商值之和
char ans[200];//计算出的二进制数组
int size=0;//二进制数组的大小为size
int len=strlen(a);
while(sum){
sum=0;
for(i=0;i<len;i++){
int num=a[i]-'0';//将字符转换为数字
sum+=num/2;//sum累加该位除以2后的商值
if(i<len-1){//当没有执行到最后一位时,将下一位的数字转换为:改位余数的十倍+下一位的数字
a[i+1]=num%2*10+a[i+1];
}
if(i==len-1){//当执行到最后一位,直接将所得的余数存到二进制数组里面
ans[size++]=num%2+'0';
}
a[i]=num/2+'0'; //将除数数组变为这次循环下的商数组,继续下次循环用
}
}
for(i=size-1;i>=0;i--)
printf("%c",ans[i]);
printf("\n");
}
return 0;
}
问题 D: 八进制
时间限制: 1 Sec 内存限制: 32 MB
题目描述
输入一个整数,将其转换成八进制数输出。
输入
输入包括一个整数N(0<=N<=100000)。
输出
可能有多组测试数据,对于每组数据,
输出N的八进制表示数。
样例输入
9
8
5
样例输出
11
10
5
Submission
#include <stdio.h>
#include <string.h>
char a[31];
int ans[100000];
int main()
{
int n,i;
while(scanf("%d",&n)!=EOF){
int size=0;
do{
ans[size++]=n%8;
n=n/8;
}while(n!=0);
for(i=size-1;i>=0;i--)
printf("%d",ans[i]);
printf("\n");
}
return 0;
}
系统地学习了这些基础的算法之后发现自己以前写不出来是件多蠢的事情…加油加油,每天都要给自己加油打气,只要专注地做一件事,就会做好的!