P进制数 x = a 1 a 2 a 3 . . . a n x = a_1a_2a_3...a_n x=a1a2a3...an转换为十进制数y:
y = a 1 ∗ P n − 1 + a 2 ∗ P n − 2 + . . . + a n − 1 ∗ P + a n y = a_1*P^{n-1}+a_2*P^{n-2}+...+a_{n-1}*P+a_n y=a1∗Pn−1+a2∗Pn−2+...+an−1∗P+an
int y = 0, product = 1; // product在循环中会不断乘P,得到1、P、P^2、...
while (x != 0)
{
y = y + (x % 10) * product; // x % 10 是为了每次获取x的个位数
x = x / 10; // 去掉x的个位
product *= P;
}
十进制数y转换为Q进制数 z = a 1 a 2 a 3 . . . a n z = a_1a_2a_3...a_n z=a1a2a3...an:
int ans[40], num = 0; // 数组ans存放Q进制数z的每一位,num为数位
do
{
ans[num++] = y % Q; // 除基取余
y = y / Q;
} while(y != 0); // 当商不为0时进行循环
ans[num] = '\0'; // 别忘加字符串终止符
这样ans数组从高位ans[num - 1]到低位ans[0]即为Q进制z,进制转换完成。不过要注意一点就是循环体用的是do…while语句而不是while。因为如果十进制数恰好等于0,那么使用while语句将使循环直接跳出,导致结果出错。实际上,十进制数y为0时其Q进制数也应为0。
问题 A: 又一版 A+B
输入两个不超过整型定义的非负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的范围。
#include
using namespace std;
int main()
{
long long A, B, C, m;
while (scanf("%lld%lld%lld", &m, &A, &B), m)
{
C = A + B;
int ans[40], num = 0;
do {
ans[num++] = C % m;
C = C / m;
} while (C);
for (int i = num - 1; i >= 0; --i)
printf("%d", ans[i]);
printf("\n");
}
return 0;
}
问题 B: 数制转换
求任意两个不同进制非负整数的转换(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
可能题目信息描述的不是很准确,我也读了很久。题目的意思是将a进制的n转换为b进制然后输出。很多人可能奇怪,既然都是整数了,为什么又扯到符号呢?其实这个“整数”的涵盖范围很大。比如十六进制的A6就是十六进制的整数,但用十进制表示不出来,所以用字母。所以输入的“整数”中是可能含有字母的,转换后的整数也是有可能含有字母的,因此要用字符串存储和表示不同进制的数。我代码中的重点在于对字符转数字以及数字转字符的处理。
#include
#include
using namespace std;
int main()
{
int a, b;
char n[40];
while (scanf("%d%s%d", &a, n, &b) != EOF)
{
int temp = 0, product = 1, num = 0; // 十进制数temp和乘积
for (int i = strlen(n) - 1; i >= 0; --i)
{
if (n[i] >= '0' && n[i] <= '9')
temp += (n[i] - '0') * product;
else if (n[i] >= 'a' && n[i] <= 'f')
temp += (n[i] - 87) * product;
else if (n[i] >= 'A' && n[i] <= 'F')
temp += (n[i] - 55) * product;
product *= a;
}
char ans[40];
do {
int y = temp % b;
ans[num++] = y >= 10 ? y + 55 : y + '0'; // 注意+55和+'0'的区别
temp /= b;
} while(temp);
ans[num] = '\0';
for (int i = num - 1; i >= 0; --i)
printf("%c", ans[i]);
printf("\n");
}
return 0;
}
问题 C: 进制转换
将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。
多组数据,每行为一个长度不超过30位的十进制非负整数。
(注意是10进制数字的个数可能有30个,而非30bits的整数)
每行输出对应的二进制数。
985
211
1126
1111011001
11010011
10001100110
非常好的一个题目,强烈建议一定要完全弄懂。最基本的思路是:用字符串来存储数字,即使是long long也只能存到18位整数;然后我们勇字符串数组模拟除法,实质就是针对每一位的除法。这是很方便的,比如5 / 2,在计算机中得到的结果就是2,也就是商,而它的余数可作为后一位的“补10”处理。注意啦,这里的“补10”要好好理解一下。最后要注意的就是在哪里设置循环,用什么循环(结合本博客最上方的常用模板那句话来理解),循环的条件怎么设置,什么时候字符转数字什么时候又反过来。细节不多说,看代码,不明白的欢迎在评论区留言,我会及时回复并且更新注释的。
#include
#include
using namespace std;
int main()
{
char dec[40];
while (scanf("%s", &dec) != EOF)
{
char bin[500];
int num = 0, re;
do
{
re = 0;
for (int i = 0; dec[i] != '\0'; ++i) // 进行每一位的除法,每位的余数向后一位进位
{
int temp = re; // 用temp保存前一位的进位
re = (dec[i] - '0') % 2; // 求出余数,更新进位
dec[i] = (dec[i] - '0'+ temp * 10) / 2 + '0'; // 做除法,记得+'0'转换为字符
}
bin[num++] = re + '0'; // 最后剩下的余数就是二进制位,别忘记re是整数,要转为字符
if (dec[0] == '0' && strlen(dec) != 1) // 如果做完除法后最高位为0,且此时还不是个位数,则需要字符串前移
{
int j = 0;
for (int i = 1; dec[i] != '\0'; ++i)
dec[j++] = dec[i];
dec[j] = '\0'; // 别忘加字符串终止符
}
} while (dec[0] != '0');
bin[num] = '\0';
for (int i = num - 1; i >= 0; --i)
printf("%c", bin[i]);
printf("\n");
}
return 0;
}
问题 D: 八进制
输入一个整数,将其转换成八进制数输出。
输入包括一个整数N(0<=N<=100000)。
可能有多组测试数据,对于每组数据,
输出N的八进制表示数。
9
8
5
11
10
5
无。
#include
using namespace std;
int main()
{
int N;
while (scanf("%d", &N) != EOF)
{
int ans[40], num = 0;
do {
ans[num++] = N % 8;
N = N / 8;
} while (N);
for (int i = num - 1; i >= 0; --i)
printf("%d", ans[i]);
printf("\n");
}
return 0;
}
一定要自己写一遍哦~~~