【问题标题】:Convert a number to Excel’s base 26将数字转换为 Excel 的基数 26
【发布时间】:2018-02-26 08:06:55
【问题描述】:

好吧,我被一些看似简单的东西困住了。我正在尝试将数字转换为基数 26(即 3 = C、27 = AA 等)。我猜我的问题与模型中没有 0 有关吗?没有把握。但是如果你运行代码,你会发现数字 52、104 尤其是 676 附近的数字真的很奇怪。谁能给我一个提示我没有看到什么?我会很感激的。 (为了避免浪费你的时间,@ 是 ascii char 64,A 是 ascii char 65)

def toBase26(x):
    x = int(x)
    if x == 0:
        return '0'
    if x < 0:
        negative = True
        x = abs(x)
    else:
        negative = False
    def digit_value (val):
        return str(chr(int(val)+64))
    digits = 1
    base26 = ""
    while 26**digits < x:
        digits += 1
    while digits != 0:
        remainder = x%(26**(digits-1))
        base26 += digit_value((x-remainder)/(26**(digits-1)))
        x = remainder
        digits -= 1
    if negative:
        return '-'+base26
    else:
        return base26

import io    
with io.open('numbers.txt','w') as f:
    for i in range(1000):
        f.write('{} is {}\n'.format(i,toBase26(i)))

所以,我通过对我的函数(while 循环中的 2 个 if 语句)进行一些更改找到了一个临时解决方法。无论如何,我的列限制为 500,并且对函数的以下更改似乎可以达到 x = 676,所以我很满意。但是,如果你们中的任何人找到任何 x 的通用解决方案(可能是我的代码可能会有所帮助),那就太酷了!

def toBase26(x):
    x = int(x)
    if x == 0:
        return '0'
    if x < 0:
        negative = True
        x = abs(x)
    else:
        negative = False
    def digit_value (val):
        return str(chr(int(val)+64))
    digits = 1
    base26 = ""
    while 26**digits < x:
        digits += 1
    while digits != 0:
        remainder = x%(26**(digits-1))
        if remainder == 0:
            remainder += 26**(digits-1)
        if digits == 1:
            remainder -= 1
        base26 += digit_value((x-remainder)/(26**(digits-1)))
        x = remainder
        digits -= 1
    if negative:
        return '-'+base26
    else:
        return base26

【问题讨论】:

  • 通常,您需要0 的符号,并且 26 应该是基数 26 的第一个两位数。比较基数 2 和 10,其中这些数字是第一个两位数和数字值范围从0n-1
  • 对,但这并不能真正解决我想要做的事情。我需要 excel 样式的列以及从列号到列标签的简单转换。
  • @不是你的零符号吗?
  • @Yaroslav 您要做的不是转换为base26。您正在尝试将数字映射到字母。
  • @Ev.考尼斯。是的,那么将 1000 转换为字母的最佳方法是什么?通过在 while 循环中添加 if remaining == 0: remaining += 26**(digits-1) ,我得到了更好的结果,但它仍然错过了 A 作为第一个“数字”

标签: python numbers base


【解决方案1】:

转换为 Excel 的“基数 26”时的问题是,对于 Excel,数字 ZZ 实际上是 26 * 26**1 + 26 * 26**0 = 702,而普通的基数 26 数字系统会生成 1 * 26**2 + 1 * 26**1 + 0 * 26**0 = 702 (BBA)。所以我们不能在这里使用通常的方法来转换这些数字。

相反,我们必须推出自己的divmod_excel 函数:

def divmod_excel(n):
    a, b = divmod(n, 26)
    if b == 0:
        return a - 1, b + 26
    return a, b

这样,我们可以创建一个to_excel 函数:

import string
def to_excel(num):
    chars = []
    while num > 0:
        num, d = divmod_excel(num)
        chars.append(string.ascii_uppercase[d - 1])
    return ''.join(reversed(chars))

换个方向,这个就简单一点

from functools import reduce
def from_excel(chars):
    return reduce(lambda r, x: r * 26 + x + 1, map(string.ascii_uppercase.index, chars), 0)

这组函数做对了:

>>> to_excel(26)
'Z'
>>> to_excel(27)
'AA'
>>> to_excel(702)
'ZZ'
>>> to_excel(703)
'AAA'
>>> from_excel('Z')
26
>>> from_excel('AA')
27
>>> from_excel('ZZ')
702
>>> from_excel('AAA')
703

我们实际上可以通过简单地检查我们是否可以将它们链接起来以重现原始数字来确认它们彼此相反地正确工作:

for i in range(100000):
    if from_excel(to_excel(i)) != i:
        print(i)
# (prints nothing)

【讨论】:

  • 你忘了定义divmod我相信。
  • @IMCoins 那个is built-in.
  • 为了你,我的好先生,我的帽子掉了。我基本上是用我的第二个功能提出您的解决方案,但您的解决方案是我正在做的事情的概括。不错。
【解决方案2】:

对不起,我是用 Pascal 写的,不懂 Python

function NumeralBase26Excel(numero: Integer): string;
var
  algarismo: Integer;
begin
  Result := '';
  numero := numero - 1;
  if numero >= 0 then
  begin
    algarismo := numero mod 26;
    if numero < 26 then
      Result := Chr(Ord('A') + algarismo)
    else
      Result := NumeralBase26Excel(numero div 26) + Chr(Ord('A') + algarismo);
  end;
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    相关资源
    最近更新 更多