各种 2 到 62 任意进制之间的转换
侧边栏壁纸
  • 累计撰写 1,061 篇文章
  • 累计收到 0 条评论

各种 2 到 62 任意进制之间的转换

加速器之家
2024-10-20 / 0 评论 / 6 阅读 / 正在检测是否收录...

我们在平时生活中通常会遇到 10 进制转其他进制,或其他进制转为 10 进制,那我们就可以通过 10 进制进行中转,实现各种任意进制的转换。

大部分编程语言都仅限在 2-36 进制内的转换,这里我们拓展到 62 进制,即小写字母z的下一位用大写字母A表示,直到大写字母Z

我们先来熟悉下 10 进制之间的转换,然后进行统一。

1. 其他进制转为 10 进制 #

其他进制转为 10 进制时,将当前的基数乘以当前的位权,然后全部相加即可,如一个 8 进制的数字 123:

123 = 1 * 8^2 + 2 * 8^1 + 3 * 8^0;
    = ((1 * 8) + 2) * 8 + 3;

通过这个简单的推导,我们在用代码实现时,可以从左到右,先用当前数字乘以进制,然后再参与下一位的运算,直到结束。

进制超过 10 时,会出现字母,这里我们需要把字母转为数字再进行计算。

字母转为数字:

/**
* 将letter转为纯数字
* @param {char} letter
* @return {int}
*/
int transformCharToNum(char letter){ if (letter >= '0' && letter <= '9') { return letter - '0'; } if (letter >= 'a' && letter <= 'z') { return letter - 'a' + 10; } if (letter >= 'A' && letter <= 'Z') { return letter - 'A' + 36; } return 0; }

其他进制转为 10 进制的具体实现:

/**
* 将进制为base的字符串数字num,转为10进制的数字
* @param {string} num 要转换的数字
* @param {int} base 该数字的进制
*/
int covertOtherTo10(string num, int base){ int p = 0, number10 = 0; while (p < num.length()) { number10 *= base; number10 += transformCharToNum(num[p]); // 将字母转为纯数字,然后参与运算 p++; } return number10; }

使用方式:

covertOtherTo10("1101", 2); // 将2进制的数字1101转为10进制,结果为13
covertOtherTo10("2e", 16); // 将16进制的数字2e转为10进制,结果为46

2. 10 进制转为其他进制 #

10 进制的数字转为其他进制的数字,我们用到的短除法,即对某进制取余,获取到的余数即为该位置的基数。

转换后的进制可能比较大,如在 16 进制中,a 表示 10,b 表示 11 等,这里我们要有一个数字到字母的对照表。

我们用 C++ 来实现下:

/**
* 将数字转为进制里的字母
* @param {int} num
* @return {char}
*/
int transformNumToChar(int num){ string str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; return str[num]; }

10 进制转为其他进制的具体实现:

string covert10ToOther(int num, int to){
  int cur;
  string result;

  while (num) {
      cur = num % to;
      result.push_back(transformNumToChar(cur)); // 将数组转为字母,如10->a
      num /= to;
  }
  reverse(result.begin(), result.end());
  return result;
}

使用方式:

covert10ToOther(13, 2); // 将10进制里的13转为2进制,结果为1101
covert10ToOther(7, 2); // 111
covert10ToOther(13, 5); // 23

3. 任意进制转任意进制 #

任意进制之间的转换,我们只需要把上面的两种方式组合在一起就行了。这里中间需要 10 进制中转一下。

我们将进制转换扩展到了 62 进制,里面可能会包含英文字符,因此我们的输入和输出都定义成了 string 类型。若您需要的是纯数字格式的,还请自行转换。

class Solution
{
public:
    /**
* 将num从base进制转为to指定的进制
* @param {string} num 要转换的数字字符串
* @param {int} base num的进制
* @param {int} to 转换后的进制
* @return {string}
*/
string covert(string num, int base, int to){ // 当base和to相等 或 base和to超出转换范围,则原样返回 if (base == to || !this->checkRadixLegal(base) || !this->checkRadixLegal(to)) { return num; } // 先转成10进制 int p = 0, number10 = 0; while (p < num.length()) { number10 *= base; number10 += this->transformCharToNum(num[p]); p++; } // 若要转换的正好是进制,则直接返回 if (to == 10) { return to_string(number10); } int cur; string result; while (number10) { cur = number10 % to; result.push_back(this->transformNumToChar(cur)); number10 /= to; } reverse(result.begin(), result.end()); return result; } private: bool checkRadixLegal(int radix){ return radix >= 2 && radix <= 62; } /**
* 将letter转为纯数字
* @param {char} letter
* @return {int}
*/
int transformCharToNum(char letter){ if (letter >= '0' && letter <= '9') { return letter - '0'; } if (letter >= 'a' && letter <= 'z') { return letter - 'a' + 10; } if (letter >= 'A' && letter <= 'Z') { return letter - 'A' + 36; } return 0; } /**
* 将数字转为进制里的字母
* @param {int} num
* @return {char}
*/
int transformNumToChar(int num){ string str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; return str[num]; } };

我们将进制扩展到了 62 进制内的任意进制,因此输入和输出均为 string 类型。

使用方式:

auto aa = new Solution();
cout << aa->covert("1101", 2, 10); // "1101"为2进制数字,将其转为10进制,结果为13
cout << aa->covert("13", 10, 5) << endl;
cout << aa->covert("7", 10, 2) << endl;
cout << aa->covert("1101", 2, 16) << endl;
cout << aa->covert("456", 7, 2) << endl;
cout << aa->covert("2e", 16, 10) << endl;
cout << aa->covert("7aZ", 62, 10) << endl;

/*
1101 from 2 to 10 is 13
13 from 10 to 5 is 23
7 from 10 to 2 is 111
1101 from 2 to 16 is d
456 from 7 to 2 is 11101101
2e from 16 to 10 is 46
7aZ from 62 to 10 is 27589
*/

我们就可以在 62 进制内实现任意进制的任意转换了。

4. JavaScript 中任意进制的转换 #

在 JavaScript 中,有两个系统方法 parseInt 和 toString,综合运用这两个方法,可以实现 36进制内的任意进制的转换。

  • parseInt(string, radix): 将任意进制 radix(36 进制内)转为 10 进制的数字,radix 表示 string 本身是多少进制的;
  • num.toString(radix): 将 10 进制的数字转为任意进制 radix 的字符串,radix 表示要转换成多少进制的;

我们这里来封装一下:

const covert = (num: string, base: number, to: number) => {
  return parseInt(num, base).toString(to);
};

使用方式与上面的 C++代码实现的方式一样:

covert('1101', 2, 10); // 13
covert('13', 10, 5); // 23
covert('2e', 16, 10); // 46

若需要扩展到更大的进制范围,就得需要自行实现了,具体实现方式可以参考上面 C++的代码。

0

评论

博主关闭了当前页面的评论