在Python中将数字转换为base 64

时间:2017-10-14 01:14:21

标签: python python-3.x encode number-theory

所以我试图编程(在Python 3中没有字符串)这个我找到的很酷的项目。

以相反的顺序返回36位数字n的6个字符的字符串表示形式作为base-64数字,其中64个数字的顺序为:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz - +

例如,

encode(0) → '000000'

encode(9876543210) → 'gR1iC9'

encode(68719476735) → '++++++'

到目前为止我所拥有的是:

def encode(n):
  SYM = {'0': 0,
         '1': 1,
         '2': 2,
         '3': 3,
         '4': 4,
         '5': 5,
         '6': 6,
         '7': 7,
         '8': 8,
         '9': 9,
         'A': 10,
         'B': 11,
         'C': 12,
         'D': 13,
         'E': 14,
         'F': 15,
         'G': 16,
         'H': 17,
         'I': 18,
         'J': 19,
         'K': 20,
         'L': 21,
         'M': 22,
         'N': 23,
         'O': 24,
         'P': 25,
         'Q': 26,
         'R': 27,
         'S': 28,
         'T': 29,
         'U': 30,
         'V': 31,
         'W': 32,
         'X': 33,
         'Y': 34,
         'Z': 35,
         'a': 36,
         'b': 37,
         'c': 38,
         'd': 39,
         'e': 40,
         'f': 41,
         'g': 42,
         'h': 43,
         'i': 44,
         'j': 45,
         'k': 46,
         'l': 47,
         'm': 48,
         'n': 49,
         'o': 50,
         'p': 51,
         'q': 52,
         'r': 53,
         's': 54,
         't': 55,
         'u': 56,
         'v': 57,
         'w': 58,
         'x': 59,
         'y': 60,
         'z': 61,
         '-': 62,
         '+': 63,}

但现在我不确定下一步该做什么。我不想使用字符串和连接等,我想使用模数和标准数论+ for / while / else方法来做这个。

我的想法是定义

r1 = n % 63
r2 = r1 % 63
r3 = r2 % 63
r4 = r3 % 63
r5 = r4 % 63
r6 = r5 % 63

但我不知道该怎么做。

我应该如何将n转换为base 64?

最后,为了在找到新的表示后反转数字,我想我只需修改10的每个幂来隔离每个数字,然后将它们放回到一起。

我应该如何编程呢?

谢谢!

1 个答案:

答案 0 :(得分:2)

这里有一些代码可以满足您的需求。 get_digit函数使用一堆if... elif测试来转换0< = d< 0中的整数d。 64到其对应的字符编号,然后使用标准chr函数将该数字转换为实际字符。 encode函数执行实际的余数计算,调用get_digit进行字符转换,并将结果保存到out列表中。我们将该列表附加'0'个字符以使其长度为6。

def get_digit(d):
    ''' Convert a base 64 digit to the desired character '''
    if 0 <= d <= 9:
        # 0 - 9
        c = 48 + d
    elif 10 <= d <= 35:
        # A - Z
        c = 55 + d
    elif 36 <= d <= 61:
        # a - z
        c = 61 + d
    elif d == 62:
        # -
        c = 45
    elif d == 63:
        # +
        c = 43
    else:
        # We should never get here
        raise ValueError('Invalid digit for base 64: ' + str(d)) 
    return chr(c)

# Test `digit`
print(''.join([get_digit(d) for d in range(64)]))

def encode(n):
    ''' Convert integer n to base 64 '''
    out = []
    while n:
        n, r = n // 64, n % 64
        out.append(get_digit(r))
    while len(out) < 6:
        out.append('0')
    return ''.join(out)

# Test `encode`
for i in (0, 9876543210, 68719476735):
    print(i, encode(i))

<强>输出

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+
0 000000
9876543210 gR1iC9
68719476735 ++++++

因为我们正在使用2的强大基础,所以

的替代方案
n, r = n // 64, n % 64

是使用按位运算

n, r = n >> 64, n & 63

稍微快些,但我想这里没有太大的区别,而且之前的代码更具可读性。 OTOH,理解为什么按位版本产生正确的结果会很有用。