问题描述
今天在工作中遇到一个问题;在使用excel的web插件的时候,需要将列数字转化为字母表示法;即
- 数字
0
的字母表示法A
- 数字
1
的字母表示法B
- 数字
25
的字母表示法Z
- 数字
26
的字母表示法AA
- 数字
27
的字母表示法AB
以此类推;我想既然写了,就写一个适应任意大的数字吧!
本来想一下使用25进制,将数字转化为字母使用最小短除法,然后得到结果,但是在实践的过程中发现,如果使用0
代表A
,那就会面临一个问题,使用字母表示法,A是可以打头的,这样就没办法进行了。
经过了两个小时的奋战,中与找到其中的规律了;过程就不记录了,直接说分析结果;在这里记录一下,以防下次使用时忘记;这个方法可能不是最简单的方法,不喜勿喷。
解决方案
1. 将字母转化为数字
字母转化为数字,0
代表A
往后以此类推,转化公式:
number = 26n-1 + word1 * 26n-1 + word2 * 26n-2 + … + wordn-1 * 261 + wordn * 260
注释:
number:表示转化后的十进制数字
word:代表将要转化的字母表示法
n:代表字符长度
word下标:代表字符的第几位,从1开始
例如:我们将FUK
转化为数字表示法
F = 5
U = 20
K = 10
n = 3
262 + 5 * 262 + 20 * 261 + 10 * 260 = 4586
则他代表的数字就是FUK
的十进制数字4586
;
2. 将字数字化为母转表示法
字母转数组稍微有点复杂,首先我们得取到对应字母表示法的长度;然后用最小短处法除以26,取得结果。
我们可以使用上面的那个方法,判断出数字所对应的字母表示法的位数;这里我们使用n
表示:
pow = pow - 26n-1
word = char(h) + … + char© + char(b) + char(a)
如果最终结果word
和第一步计算的长度相等,则word
就是结果;如果比计算长度小1,则word
需要在第一位补充一个A
;
这里就不举例子了,补上一段js的实现代码:
numberToLet = (pow) => {
// 如果待计算数字小于26,直接计算即可
if(pow < 26) {
return String.fromCharCode(pow + 65);
}
// 计算目标字符串的长度
let size = 1;
while(true) {
let sum = Math.pow(26, size);
for(let i = size;i >= 0;i--) {
sum += 25 * Math.pow(26, i);
}
if(pow <= sum) {
break;
}
size++;
}
// 首先去掉影响值
pow = pow - Math.pow(26, size);
// 最小短除法的实现
let arr = []
while(true) {
arr.push(pow % 26);
pow = Math.floor(pow / 26);
if(pow === 0) {
break;
}
}
// 结果拼接
let rtbStr = '';
for(let item of arr) {
rtbStr = String.fromCharCode(item + 65) + rtbStr;
}
// 检测长度是否达标
if(rtbStr.length === size) {
rtbStr = 'A' + rtbStr;
}
return rtbStr;
}