由于进制转换属于基础且比较重要,所以我就写一个博客方便自己复习,过程中如有错误,还请指出。
常用的进制有二进制,八进制,十进制和十六进制。
常用的进制转换就是十进制转换成其他进制和其他进制转换成十进制
我们先来讲其他进制转换成十进制。我们先看个例子,比如有一个十进制数字是666
那我们可以分解为6*10^2 + 6*10^1 + 6*10^0 ,这个分解求和出来的结果是十进制数字的,那么同理,如果有一个二进制数字1011,想转换成十进制数字就可以变成, 1*2^3 + 0*2^2 + 1*2^1 + 1*2^0. 得到的结果是11,那这个11就是1011转换成十进制数的结果.有了这个基础,我们就可以写一段代码来求了
先包含头文件
1.由于得到的是十进制数,所以返回值类型是int
2.由于其他进制可能原本包含字母(比如16进制就包含A,B,C,D,E,F),所以形参用string来接收,base是本来的进制数,比如16进制转换成10进制,base就是16
3.这里的做法是从高位开始取,也就是从s的下标0开始,字符串的左边是高位,右边是低位,为什么这样做呢?因为我们后面可以用动态权值累加的方法,比较方便和容易理解。
4.下面的动态权值累加是核心代码,务必要理解,这里其实可以用分配律来理解
比如有一个16进制数1AB,那么执行下来就是
ans = 0 * 16 + 1 == 1 * 16^0
ans = 1 * 16 + 10 == 1 * 16^1 + 10 * 16^0
ans = 26 * 16 + 11 == (16 + 10) * 16^1 + 11 == 1 * 16^2 + 10 * 16^1 + 11 * 16^0
可以看到,从高位开始乘,如果后面还有位数,那之前乘过的位数上的数字都会乘上一个进制数base,这样子我们就可以模拟出手算的过程了
接下来是十进制转换成其他进制,一般都是用连除法,即这个数每次都除以要转换的进制数,记录下来余数,再将得到的结果继续除,直到得到的结果为0停止,此时记录下来的余数,最开始记的是低位,也就是在最右边,最后面记的是高位,也就是最左边
1.其他进制可能有字母,所以返回值类型是string,要传入的是十进制数和要转换成的进制base
2.while里面的temp是int类型,所以转换成字符型数字要加个字符'0',ans是string类,虽然会隐式转换,但显式转换更直观一点,也可以避免潜在风险
3.最后,由于我们第一次得到的余数记录在string是最左边(高位),但是第一次得到的余数是低位的,所以我们需要逆转一下,最后返回就行
完整代码如下:
#include <iostream>
#include <string> //用到string函数库的内容
#include <algorithm> //reverse()函数头文件
using namespace std;
int charToValue(char c)
{
if (c >= '0' && c <= '9') {
return c - '0';
}
else if (c >= 'a' && c <= 'z') {
return 10 + c - 'a';
}
else if (c >= 'A' && c <= 'Z') {
return 10 + c - 'A';
}
cout << "Your char error" << endl;
}
int changeToDecimal(string s, int base) //s是传进来要修改的数值,base是原本的进制数
{
int ans = 0;
for (int i = 0; i < s.size(); i++) { //从高位开始取
int value = charToValue(s[i]); //将字符转换成对应数字
if (value > base) { //数字超过进制数,代表这段数值是不合理的
cout << "Your value beyond range" << endl;
return -1;
}
//从最左端(最高位)开始算起,每经过下一位,这个位置都会乘上权值(比如16进制就是16)
//所以假设有n位,那么我们这个算法乘下来从左到右就是乘了 k^n-1, k^n-2, k^n-3, ..... k^0
ans = ans * base + value; //动态权值累加
}
return ans;
}
//十进制转换为其他进制
string decimalToOther(int decimal, int base) //十进制数,要转换的进制
{
if (decimal == 0) return "0"; //做一个特判,为0直接返回字符串
string ans = "";
while (decimal != 0) //连除法
{
int temp = decimal % base; //模拟手算的求余过程
//转换成字符
if (temp >= 0 && temp <= 9) {
ans += (char)('0' + temp);
}
else if (temp > 9){
ans += (char)(temp + 'A' - 10);
}
decimal /= base; //舍掉末尾
}
reverse(ans.begin(), ans.end()); //逆序函数,第一个参数是元素的首地址,第二个参数是要结束的位置的下一位
return ans;
}
void testjinzhi()
{
string s;
int base;
//base进制转换为10进制
cin >> s >> k;
cout << "其他进制转换为10进制: " << changeToDecimal(s, base) << endl;
cout << "10进制转换为其他进制: " << decimalToOther(666, base) << endl;
}
int main()
{
testjinzhi();
return 0;
}
讲的不是很好,有问题可以评论区交流一下,或者可以看看别人的教程,或许更容易懂