请教一个算法问题,把数字转换为A,B,C……,如何实现?
现在我想根据数字转换为英文字母:比如 A->1,B->2,……AA->27,AB->28。我的思路本来是想维护一个数组,然后根据辗转相除法,然后生成对应的下标,但是有问题:
function numToLetter(originNum = 53) {
let letter = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
let num = originNum; // 随意输入一个数字
let numArr = []; // 得到num对应的字母下标
// 辗转相除,然后取余数
while (num > 0) {
numArr.push(num % 26);
num = Math.floor(num / 26);
}
console.log('**********************************')
// 输出对应数字的字母下标
console.log(`${originNum}对应的字母下标为`, numArr.reverse());
let str = ''; // 数字对应的字符串
numArr.forEach(v => {
str += letter[v-1]
})
console.log('这个字符串为:', str)
}
numToLetter(53)
numToLetter(52)
53 = 26^1 * 2 + 26^0 * 152 = 26^1 * 2 + 26^0 * 1
26 进制是这样算的,但是转换为下标的话,这样写有问题,不知道如何优化,或者别的思路求数字转字母
回复
1个回答

test
2024-07-20
首先,这个“26 进制”不是标准 26 进制,是双射 26 进制(Bijective positional notation [wiki])
在双射 k 进制下,$$\overline{a_na_{n−1} \cdots a_1a_0} = a_nk^n + a_{n-1}k^{n-1} + \cdots + a_1k + a_0 $$
其中 $$\{1, 2, \cdots, k \}$$ 是双射 k 进制使用的数字。
所以,直接取余才会遇到没法处理余数是 0
的情况。
用我们更为熟悉的十进制来类比一下
在双射十进制中,假定使用 1-9
和 A
这 10 个数字。
10
->(1, 0)
->A
11
->(1, 1)
->11
20
->(2, 0)
->1A
- ...
100
->(1, 0, 0)
->9A
110
->(1, 1, 0)
->AA
111
->(1, 1, 1)
->111
那么,遇到余数是 0
怎么办?以双射十进制下表达 100
为例(手算过程,伪代码)
X = 100
MOD_1 = 100 % 10
if (! MOD_1) { // 余数是 0,但没有数字 0,怎么办?
X -= 10 // 只好从上一位“借走”10
MOD_1 = 10 // 这样,这一位就是数字 A 了
}
X /= 10 // 90 / 10 == 9
MOD_2 = 9 % 10
// 数字 9,没问题
X /= 10 // 9 / 10 == 0,结束
Y = MOD_2 ++ MOD_1 // 9A,没问题
现在我们可以改进原来的代码:
function numToLetter(originNum = 53) {
let letter = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
let num = originNum; // 随意输入一个数字
let numArr = []; // 得到num对应的字母下标
// 辗转相除,然后取余数
while (num > 0) {
+ let mod = num % 26;
+ if (! mod) {
+ num -= 26;
+ mod = 26;
+ }
- numArr.push(num % 26);
+ numArr.push(mod)
num = Math.floor(num / 26);
}
console.log('**********************************')
// 输出对应数字的字母下标
console.log(`${originNum}对应的字母下标为`, numArr.reverse());
let str = ''; // 数字对应的字符串
numArr.forEach(v => {
str += letter[v-1]
})
console.log('这个字符串为:', str)
}
结果:
numToLetter(52)
// **********************************
// 676对应的字母下标为
// Array [ 1, 26 ]
// 这个字符串为: AZ
numToLetter(26 * 26) // 676
// **********************************
// 676对应的字母下标为
// Array [ 25, 26 ]
// 这个字符串为: YZ
numToLetter(26 * 26 + 26) // 702
// **********************************
// 702对应的字母下标为
// Array [ 26, 26 ]
// 这个字符串为: ZZ
回复

适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容