在编程中,进制转换是一个非常常见的操作。我们常常需要将一个数从一种进制转换为另一种进制。例如,二进制、十进制、十六进制等不同进制的数值广泛应用于计算机科学、数学以及编程中。掌握进制转换的技巧,不仅能帮助我们理解不同数值表示的方式,还能在多种算法中提高效率。
在本文中,我们将探讨如何使用 C++ 实现从任意进制到任意进制的转换,并对代码进行优化,使其更加高效和可读。
进制转换的核心思想非常简单,主要有两种情况:
从十进制转换到其他进制的操作,我们需要将十进制数除以目标进制并记录余数。重复此过程直到商为零,并且将余数反转,就得到了目标进制数的每一位。
void ten_to_else(int num, int k, string &s) {
if (num == 0) {
s = "0"; // 防止 num == 0 时没有结果
return;
}
while (num) {
s += dig[num % k];
num /= k;
}
reverse(s.begin(), s.end()); // 翻转结果
}
这段代码实现了将十进制数 num
转换成 k
进制的字符串表示。特别地,我们处理了 num == 0
的特殊情况,确保程序可以正确返回 "0"
。
对于从其他进制转换为十进制的操作,我们遍历输入字符串中的每一个字符,找出它对应的数值,并根据目标进制进行加权累加,最终得出十进制的结果。
int else_to_ten(string &num, int k) {
int ans = 0;
for (int i = 0; i < num.size(); i++) {
int tmp = dig.find(num[i]);
if (tmp == string::npos || tmp >= k) {
// 字符不在 dig 中,或者不符合目标进制
return -1;
}
ans = ans * k + tmp;
}
return ans;
}
这里,我们遍历了输入字符串的每一个字符,使用 dig.find()
找出每个字符在 dig
字符集中的位置,从而得到对应的数值。随后,我们按进制的权重计算出最终的十进制数。
还有一个简单的方法,参考上一篇文章链接来实现这个功能
int else_to_ten(string &num, int k) {
return stoi(num,nullptr,k);
}
主函数负责接受用户输入,并调用相应的转换函数将输入的数值从源进制转换到目标进制,最后输出结果。
int main() {
string num, res;
int sour, des;
cout << "请按以下规则输入:" << endl;
cout << "一串数字 该数字的进制 转化后的进制" << endl;
cin >> num >> sour >> des;
// 转换为10进制
int tmp = else_to_ten(num, sour);
if (tmp == -1) {
cout << "输入的数字不符合源进制的规则" << endl;
return 1;
}
// 转换为目标进制
ten_to_else(tmp, des, res);
cout << sour << "进制下的" << num << "转换为" << des << "进制下的" << res << endl;
return 0;
}
尽管上述代码能够完成基本的进制转换功能,但通过一些优化,我们可以让程序更高效、更健壮、更具可读性。以下是几个优化点:
在 ten_to_else
函数中,我们使用了递归来完成十进制到其他进制的转换。虽然递归简单易懂,但它可能导致栈溢出,特别是在处理较大数值时。因此,使用循环来代替递归不仅能避免栈溢出,还能提高性能。
else_to_ten
函数在遇到非法字符时返回 -1,表示转换失败。在主函数中,我们可以根据这个返回值进行判断,并输出明确的错误提示,帮助用户快速定位问题。
dig
字符集dig
字符串包含了超过所需的字符。实际上,最多只需要支持到36进制,因此我们可以精简 dig
字符集,保留从 0
到 9
和从 A
到 Z
的字符。
#include <bits/stdc++.h>
using namespace std;
string dig = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 只保留有效字符
// 十进制数num转换成k进制
void ten_to_else(int num, int k, string &s) {
if (num == 0) {
s = "0";
return;
}
while (num) {
s += dig[num % k];
num /= k;
}
reverse(s.begin(), s.end()); // 翻转结果
}
// k进制数num转换成10进制
//int else_to_ten(string &num, int k) {
// int ans = 0;
// for (int i = 0; i < num.size(); i++) {
// int tmp = dig.find(num[i]);
// if (tmp == string::npos || tmp >= k) {
// // 字符不在 dig 中,或者不符合目标进制
// return -1;
// }
// ans = ans * k + tmp;
// }
// return ans;
//}
int else_to_ten(string &num, int k) {
return stoi(num,nullptr,k);
}
int main() {
string num, res;
int sour, des;
cout << "请按以下规则输入:" << endl;
cout << "一串数字 该数字的进制 转化后的进制" << endl;
cin >> num >> sour >> des;
// 转换为10进制
int tmp = else_to_ten(num, sour);
if (tmp == -1) {
cout << "输入的数字不符合源进制的规则" << endl;
return 1;
}
ten_to_else(tmp, des, res);
cout << sour << "进制下的" << num << "转换为" << des << "进制下的" << res << endl;
return 0;
}
通过本文的讨论,我们实现了一个功能完整的进制转换程序,并对代码进行了优化。程序首先将输入的数字从源进制转换为十进制,然后再将十进制转换为目标进制。这一过程通过循环和字符查找来实现,避免了栈溢出和非法字符的问题。
优化后的程序不仅提升了性能,还增强了用户体验,使其更健壮、易于理解和维护。掌握进制转换的基本算法,对于编程中遇到的各类问题非常有帮助。希望本文的讲解和代码实现能够帮助你更好地理解和使用进制转换方法。如果你有任何问题或想法,欢迎在评论区与我分享!