1. 题目来源
链接:进制转换
来源:牛客网
2. 题目说明
给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数
输入描述:
输入为一行,一共4个整数,分别为A - B、B - C、A + B、B + C,用空格隔开。 范围均在-30到30之间(闭区间)。
输出描述:
为每个测试实例输出转换后的数,每个输出占一行。如果N大于9,则对应的数字规则参考16进制(比如,10用A表示,等等)
示例1
输入
7 2
输出
111
3. 题目解析
本题思路很简单,首先想清楚原理:N进制数,每个进制位的值分别是:
x
0
∗
N
0
、
x
1
∗
N
1
、
x
2
∗
N
2
、
x
3
∗
N
3
.
.
.
x_0*N^0、x_1*N^1、x_2*N^2、x_3*N^3...
x0∗N0、x1∗N1、x2∗N2、x3∗N3...
x
0
、
x
1
、
x
2
、
x
3
.
.
.
x_0、x_1、x_2、x_3...
x0、x1、x2、x3...就是这些进制位的值,就是就是进行取模余数就是当前低进制的位的值是多少,通过除掉进制数,进 入下一个进制位的计算。
需要注意以下几点:
1.十进制数为负数时,这个时候就需要将十进制数转换成一个整数进行转换,只不过在最后输出的时候在结果加上一个负号即可。
2.输出的值不止是阿拉伯数字,当进制大于9时还有A-F,可以使用一个数组保存或者字符串保存,对余数进行判断即可。
3.辗转相除得到的结果最后输出需要逆序,因为计算的结果是反的。
4. 代码展示
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
//要考虑进制大于9的情况,还要考虑负数
string s, s1 = "0123456789ABCDEF";
int m, n;
cin >> m >> n;
bool flag = false;
// 如果为负数,则转成正数,并标记一下
if (m < 0)
{
m = - m;
flag = true;
}
// 按照进制换算成对应的字符添加到s
while (m)
{
s += s1[m % n];
m /= n;
}
// 如果为负数,结果加上符号
if (flag)
s += '-';
// 类似辗转相除倒序的情况,需要逆置
reverse(s.begin(), s.end());
cout << s << endl;
return 0;
}
2021 04 22 更新。
规律推导如上。在求解 10 进制的每一位数的时候,就是求解 10 进制下的数位系数,这也能等价拓展到任意进制。即 %p
、/=p
。注意负数情况。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int n, p;
string s = "0123456789ABCDEF";
int main() {
cin >> n >> p;
vector<char> vt;
int flag = 1;
if (n < 0) flag = -1, n = -n;
while (n) {
vt.push_back(s[n % p]);
n /= p;
}
reverse(vt.begin(), vt.end());
if (flag == -1) cout << "-";
for (auto e:vt) cout << e;
cout << endl;
return 0;
}
2021 04 22 更新。
进制转换进一步讨论,当输入的 n
比较大的时候就需要考虑采用高精度了。
链接:3373. 进制转换
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string n;
while (cin >> n) {
vector<int> a;
for (auto &e : n) a.push_back(e - '0');
reverse(a.begin(), a.end());
vector<int> res;
while (a.size()) {
int r = 0;
for (int i = a.size() - 1; ~i; i -- ) { // 核心操作,高精度除法求余数
a[i] += r * 10;
r = a[i] % 2;
a[i] /= 2;
}
res.push_back(r);
while (a.size() && a.back() == 0) a.pop_back();
}
reverse(res.begin(), res.end());
for (auto &e : res) cout << e;
cout << endl;
}
return 0;
}
a
进制转 b
进制可以直接进行转换,而不需要通过 10 进制的中转。
贴个板子:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int a,b;
string a_line, b_line;
cin >> a >> b >> a_line;
// b是将要转换的进制
vector<int> number;
for(auto c : a_line)
{
if(c >= '0' && c <= '9') number.push_back(c - '0');
if(c >= 'A' && c <= 'Z') number.push_back(c-'A' + 10);
if(c >= 'a' && c <= 'z') number.push_back(c -'a' + 36);
}
reverse(number.begin(),number.end());
vector<int> res;
while(number.size())
{
int r = 0;
for(int i = number.size()-1; i >= 0;i--)
{
number[i] += r * a;
r = number[i] % b;
number[i] /= b;
}
res.push_back(r);
while(number.size() && number.back()==0) number.pop_back(); // 把前面的0去掉
}
reverse(res.begin(),res.end()); // 求得得进制数
for(int i = 0;i < res.size();i++)
{
int a = res[i];
if(a >= 0 && a <= 9) b_line += char(a + '0');
if(a >= 10 && a <= 35) b_line += char(a - 10 + 'A');
if(a >= 36) b_line += char(a - 36 + 'a');
}
cout << a << " "<< a_line<<endl;
cout << b << " "<<b_line << endl;
cout << endl;
}
return 0;
}