各种进制转换,记起来很麻烦吗?这次一网打尽!!!
进制转换我个人总结包括以下两种,首先我先给出一些基础概念。
low:小于10的数
high:大于10的数
那么进制转换就是以下情况。
low | 10 | low |
low | 10 | high |
high | 10 | low |
higj | 10 | high |
举个例子,按照表中第一种情况就是:3进制->10进制->9进制
任何转换问题都可以视为这种方法,这种一定可以写出来,当然了,有些转换没必要这么麻烦,但是,这是一个通用方法,针对那些奇形怪状的转换。
表1类型
因为low小于10,那么我们只需要把10这个字符串,每一位都算出来并且加起来,就得到这个10进制了,比如说
3转10:现在有一个3进制的“210”,那么转为10进制就是2x3^2+1x3^1+0x3^0=18+3=21
现在我们只需要把10进制的21每次进行取模运算得到字符串就行,比如说
10进制转9进制,现在有一个21,那么就是21%9=2,然后21/9=2;一轮结束后对2再重复操作,因此3进制是”22“,
代码如下:low->10->low
int threeToTen(string str) {
int ans = 0;
int len = str.size() ;
for (int i = 0; i < len; i++) {
int temp =pow(3,len-i-1) * (str[i] - '0');
ans += temp;
}
return ans;
}
string tenToSeven(int num) {
string ans = "";
while (num) {
ans = to_string(num % 7) + ans;
num /= 7;
}
return ans;
}
现在再来一个表2类型
我们要实现4进制转12进制。那么按照思路,也就是4->10->12,现在假如有一个4进制的”321“
4->10:我们还是把4进制数按照每位求和得到10进制:3*4^2+2*4^1+1*4^0=48+8+1=57
现在把10进制57转为12进制
10->12:这里因为12进制涉及到字母A,B了但本质还是取模,57%12=9,57/12=4,再对4重复
因此代码如下:low->10->high
int fourToTen(string str) {
int ans = 0;
int len = str.size();
for (int i = 0; i < len; i++) {
int temp = pow(4, len - i - 1)*(str[i]-'0');
ans += temp;
}
return ans;
}
string tenTotwe(int num) {
string ans = "";
string tweList = "0123456789AB";
while (num) {
ans = tweList[num % 12] + ans;
num /= 12;
}
return ans;
}
总结一下,上面两个代码重复性很高,唯一区别就在于10进制转其他进制的时候,是直接求和还是根据字符串下标求值。
我们再来看看表3这种情况
我们要实现15进制转6进制。那么按照思路,也就是15->10->6,现在假如有一个15进制的”EA1“
15->10:把15进制按照每位求和得到10进制:E*15^2+A*4^1+10*15^0=3150+150+1=3301
现在把10进制3191转为6进制
10->6:本质还是取模,3191%6=5,3191/6=531,再对531重复
因此代码如下:high->10->low
int fivtToten(string str) {
int ans = 0;
int len = str.size();
for (int i = 0; i < len; i++) {
if (str[i] >= '0' && str[i] <= '9') {
ans += pow(15, len - i - 1) * (str[i] - '0');
}
else if (str[i] >= 'A' && str[i] <= 'E') {
int temp1 = pow(15, len - i - 1);
int temp2= (str[i] - 'A' + 10);
ans += pow(15, len - i - 1) * (str[i] - 'A'+10);
}
else if (str[i] >= 'a' && str[i] <= 'e') {
ans += pow(15, len - i - 1) * (str[i] - 'a' + 10);
}
else {
cout << "输入非法" << endl;
return -1;
}
}
return ans;
}
string tenTosix(int num) {
string ans = "";
while (num) {
ans = to_string(num % 6) + ans;
num /= 6;
}
return ans;
}
现在再来一个表4类型
我们要实现14进制转11进制。那么按照思路,也就是14->10->11,现在假如有一个14进制的”D21“
14->10:把4进制数按照每位求和得到10进制:13*14^2+2*14^1+1*14^0=2548+28+1=2577
现在把10进制2577转为11进制
10->11:本质还是取模,2577%11=3,2577/11=334,再对334重复
因此代码如下:low->10->high
int foutToten(string str) {
int ans = 0;
int len = str.size();
//string strList = "0123456789ABCD";
for (int i = 0; i < len; i++) {
if (str[i] >= '0' && str[i] <= '9') {
ans += pow(14, len - i - 1) * (str[i] - '0');
}
else if (str[i] >= 'A' && str[i] <= 'D') {
ans += pow(14, len - i - 1) * (str[i] - 'A'+10);
}
else if (str[i] >= 'a' && str[i] <= 'd') {
ans += pow(14, len - i - 1) * (str[i] - 'a' + 10);
}
else {
cout << "输入非法" << endl;
return -1;
}
}
return ans;
}
string tenToele(int num) {
string ans = "";
string ansList = "0123456789ABCD";
while (num) {
ans = ansList[num % 11] + ans;
num /= 11;
}
return ans;
}
总结一下,high->10的时候,其实就是先判断字符串还是数字,然后没什么区别,10->low或者high和之前完全一样。
到这里,有的小伙伴可能会说,你这个写的太麻烦了,我一个2进制转16进制完全不需要这样写,只需要补位之后算就行。
我的回答是:你是对的,因为2进制转16进制算特殊情况,当然可以,但是本文强调是针对任意进制转换,所以看起来麻烦。当然了,我们也会写一下这种特殊情况,方便我们少走弯路。
string twoTosix(string str) {
string ans = "";
string ansList = "0123456789ABCDEF";
//补全
while (str.size() % 4 != 0) {
str = '0' + str;
}
//计算
for (int i = 0; i < str.size(); i+=4) {
string tempStr = str.substr(i, 4);
int tempNum = 0;
for (int j = 0; j < tempStr.size(); j++) {
tempNum = tempNum * 2 + (tempStr[j] - '0');
}
ans += ansList[tempNum];
}
return ans;
}