数的进制转换
编写一个程序,可以实现将一个数字由一个进制转换为另一个进制。
这里有 62 个不同数位 {0−9,A−Z,a−z}。
输入格式
第一行输入一个整数,代表接下来的行数。
接下来每一行都包含三个数字,首先是输入进制(十进制表示),然后是输出进制(十进制表示),最后是用输入进制表示的输入数字,数字之间用空格隔开。
输入进制和输出进制都在 2 到 62 的范围之内。
(在十进制下)A=10,B=11,…,Z=35,a=36,b=37,…,z=61 (0−9 仍然表示 0−9)。
输出格式
对于每一组进制转换,程序的输出都由三行构成。
第一行包含两个数字,首先是输入进制(十进制表示),然后是用输入进制表示的输入数字。
第二行包含两个数字,首先是输出进制(十进制表示),然后是用输出进制表示的输入数字。
第三行为空白行。
同一行内数字用空格隔开。
输入样例:
8
62 2 abcdefghiz
10 16 1234567890123456789012345678901234567890
16 35 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 23 333YMHOUE8JPLT7OX6K9FYCQ8A
23 49 946B9AA02MI37E3D3MMJ4G7BL2F05
49 61 1VbDkSIMJL3JjRgAdlUfcaWj
61 5 dl9MDSWqwHjDnToKcsWE1S
5 10 42104444441001414401221302402201233340311104212022133030
输出样例:
62 abcdefghiz
2 11011100000100010111110010010110011111001001100011010010001
10 1234567890123456789012345678901234567890
16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 333YMHOUE8JPLT7OX6K9FYCQ8A
35 333YMHOUE8JPLT7OX6K9FYCQ8A
23 946B9AA02MI37E3D3MMJ4G7BL2F05
23 946B9AA02MI37E3D3MMJ4G7BL2F05
49 1VbDkSIMJL3JjRgAdlUfcaWj
49 1VbDkSIMJL3JjRgAdlUfcaWj
61 dl9MDSWqwHjDnToKcsWE1S
61 dl9MDSWqwHjDnToKcsWE1S
5 42104444441001414401221302402201233340311104212022133030
5 42104444441001414401221302402201233340311104212022133030
10 1234567890123456789012345678901234567890
思路
朴素做法:将读入进来的数转换成10进制,再将其转换成所需进制。
观察将数转换成所需进制的过程, 发现确定每一位数时只需要得到这个数除以所需进制数的余数即可。
由于一个数不论以何种进制表示,其除以一个数的余数都是一样的。
所以可以直接将某进制的数除以另一进制的进制数,以此得到余数,构建所需进制的数。
注意本题需要高精度维护
ccytpe头文件
isdigit(x)判断字符是否为数字
isupper(x)判断字符是否为大写字母
islower(x)判断字符是否为小写字母
代码
点击查看代码
#include<iostream>
#include<vector>//注意要加头文件
#include<algorithm>
#include<cctype>
using namespace std;
const char nl = '\n';
//string s1;
string change(int a,string s1,int b){ //string也可以作为函数返回值
vector<int> v1,v2;
string s2; //初始化
// for(int i = 0; i <= s1.size() - 1; i ++ ){
// if(s1[i] >= '0' && s1[i] <= '9')v1.push_back(s1[i]-'0');
// else if(s1[i] >= 'A' && s1[i] <= 'Z')v1.push_back(s1[i]-'A'+10);
// else v1.push_back(s1[i]-'a'+36); //共26个字母
// }
for(auto x:s1){
if(isdigit(x))v1.push_back(x-'0');
else if(isupper(x))v1.push_back(x-'A'+10);
else v1.push_back(x-'a'+36);
}
//模拟求余数的过程
reverse(v1.begin(),v1.end()); //使最高位在vector的后面,方便去除前导零
while(v1.size()){
int r = 0; //保存余数
for(int i = v1.size() - 1; i >= 0; i -- ){ //计算从最高位开始
int t = v1[i] + r * a; //更新用来计算的值(因为是a进制所以要乘a,类比10进制中药要乘10)
r = t % b; //新余数
v1[i] = t / b; //更新值(除到v1为空,即为0)
}
v2.push_back(r);
while(!v1.back() && v1.size())v1.pop_back(); //去除前导0防止死循环
}
reverse(v2.begin(),v2.end()); //再次逆转得到正序数
//还原
for(auto x:v2){
if(x >= 0 && x <= 9)s2 += x + '0';
//如果直接用s[cnt++]赋值的话(使用下标访问的值大于s.size())会出现不可预料的后果
//如:s.empty()始终为空,s.size()始终为0,即cout << s2 << nl;输出为空白
else if(x >= 10 && x <= 35)s2 += x - 10 + 'A';
else s2 += x - 36 + 'a';
}
return s2;
}
int main(){
int m;
cin >> m;
while(m -- ){
int a,b;
string s1;
cin >> a >> b >> s1;
cout << a << " " << s1 << nl;
cout << b << " " << change(a,s1,b) << nl;
cout << nl;
}
}