1. 问题分析
本题要求实现一个通用的进制转换器,能够将任意 a 进制(2 ≤ a ≤ 36)的数转换为 b 进制(2 ≤ b ≤ 36)的数。输入的数字可能包含字母(a-z 表示 10-35),输出也需要用字母表示大于 9 的数字。
核心思路是采用"以十进制为桥梁"的两步转换法:
- a 进制 → 十进制:将输入的 a 进制数按权展开,转换为十进制整数。
- 十进制 → b 进制:使用"除 b 取余法"将十进制整数转换为 b 进制数。
2. 算法设计
2.1 a 进制转十进制
遍历输入字符串的每一位:
- 如果字符是
'0'-'9',则其数值为ch - '0'。 - 如果字符是
'a'-'z',则其数值为ch - 'a' + 10。 - 如果字符是
'A'-'Z',则其数值为ch - 'A' + 10。
累加计算:decimal = decimal * a + digit_value。
2.2 十进制转 b 进制
使用循环,不断对十进制数进行取模和除法操作:
- 取余数
decimal % b,得到当前最低位的数值。 - 将余数转换为对应的字符(0-9 或 a-z)。
- 将结果字符拼接到结果字符串的前面(或最后反转)。
- 更新
decimal = decimal / b,直到decimal为 0。
3. 代码实现
cpp
#include <iostream>
#include <string>
#include <algorithm> // for reverse
using namespace std;
// 将字符转换为对应的数值
int charToValue(char ch) {
if (ch >= '0' && ch <= '9') {
return ch - '0';
} else if (ch >= 'a' && ch <= 'z') {
return ch - 'a' + 10;
} else if (ch >= 'A' && ch <= 'Z') {
return ch - 'A' + 10;
}
return 0; // 不会发生
}
// 将数值转换为对应的字符
char valueToChar(int val) {
if (val >= 0 && val <= 9) {
return '0' + val;
} else {
return 'a' + (val - 10);
}
}
int main() {
int a, b;
string num;
cin >> a >> b;
cin >> num;
// Step 1: a进制 -> 十进制
long long decimal = 0; // 使用 long long 防止溢出
for (char ch : num) {
decimal = decimal * a + charToValue(ch);
}
// Step 2: 十进制 -> b进制
string result = "";
if (decimal == 0) {
result = "0";
} else {
while (decimal > 0) {
result += valueToChar(decimal % b);
decimal /= b;
}
reverse(result.begin(), result.end());
}
cout << result << endl;
return 0;
}
4. 代码详解
charToValue函数 :将字符'0'-'9'、'a'-'z'、'A'-'Z'统一转换为对应的整数值(0-35)。valueToChar函数:将整数值(0-35)转换回字符。题目要求输出小写字母,因此这里统一返回小写。- 数据类型 :使用
long long来存储十进制中间结果,因为当 a 进制数位数较多时,十进制值可能超过int范围。 - 特殊处理 :当输入为
"0"时,直接输出"0",避免while循环不执行导致结果为空。 - 结果反转 :
除 b 取余法得到的是从低位到高位的顺序,最后需要用reverse反转得到正确顺序。
5. 测试样例
输入:
16 32
abcdef
计算过程:
abcdef(16进制) =10*16^5 + 11*16^4 + 12*16^3 + 13*16^2 + 14*16^1 + 15*16^0= 11259375 (十进制)- 11259375 转换为 32 进制:
- 11259375 % 32 = 15 →
f - 351855 % 32 = 15 →
f - 10995 % 32 = 19 →
j - 343 % 32 = 23 →
n - 10 % 32 = 10 →
a - 0 % 32 = 0 →
0(循环结束) - 反转得到:
anjff
- 11259375 % 32 = 15 →
输出:
anjff
与题目样例完全一致。
6. 总结
本题是进制转换的经典题型,核心在于理解"以十进制为桥梁"的转换思想。代码实现时需要注意:
- 字符与数值之间的正确映射。
- 使用
long long避免整数溢出。 - 处理输入为
"0"的特殊情况。 - 输出结果时注意大小写要求(本题要求小写)。
掌握了这个通用解法,就可以轻松应对 2-36 进制之间的任意转换问题了。