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

蚊子前端博客
发布于 2022-04-28 21:00
如何实现一个任意进制转换的方法

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

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

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

1. 其他进制转为 10 进制

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

COPYSHELL

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

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

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

字母转为数字:

COPYCPP

/** * 将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 进制的具体实现:

COPYCPP

/** * 将进制为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; }

使用方式:

COPYCPP

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

2. 10 进制转为其他进制

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

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

我们用 C++ 来实现下:

COPYCPP

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

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

COPYCPP

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; }

使用方式:

COPYCPP

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

3. 任意进制转任意进制

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

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

COPYCPP

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 类型。

使用方式:

COPYCPP

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 表示要转换成多少进制的;

我们这里来封装一下:

COPYJAVASCRIPT

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

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

COPYJAVASCRIPT

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

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

标签:
阅读(336)

公众号:

qrcode

微信公众号:前端小茶馆

公众号:

qrcode

微信公众号:前端小茶馆