2017-10-15 103 views
2

因此,我正在尝试编写一个程序来解码6个字符的base-64数字。从字符串转换为数字

这是问题所在语句:

返回表示为由6个字符的字符串s以相反的顺序碱-64编号的36比特的数,其中的64个数字的顺序是:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz- +

解码( '000000')→0

解码( 'gR1iC9')→

解码( '++++++')→68719476735

我想这样做不附带任何条件。

这样做将创建下列函数的反函数的最简单方法:

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,, 68719476735): 
    print(i, encode(i)) 

输出

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+ 
0 000000 
gR1iC9 
68719476735 ++++++ 

里面居然从下午2Ring是this页。

我该如何写这个程序的逆向?

甲开始:

get_digits的倒数如上低于:

def inv_get_digit(c): 

    if 0 <= c <= 9: 
     d = ord(c) - 48 
    elif 'A' <= c <= 'Z': 
     d = ord(c) - 55 
    elif 'a' <= c <= 'z' 
     d = ord(c) - 61 
    elif c == '+': 
     d = 63 
    elif c == '-': 
     d = 62 
    else: 
     raise ValueError('Invalid Input' + str(c)) 
    return d 


def decode(n): 

    out = [] 
    while n: 
     n, r= n % 10, n ** (6-len(str)) 
     out.append(get_digit(r)) 
    while len(out) < 10: 
     out.append('0') 
    return ''.join(out) 
+0

请尝试自己编写一些代码。正如我所说[这里](https://stackoverflow.com/questions/46739875/converting-a-number-to-base-64-in-python/46740374#comment80448645_46740374),第一步是反转'get_digit',我给你一个提示如何做到这一点。 –

+0

我编辑了我的帖子以反映您的评论。我没有在评论中发布新代码,因为格式有偏差。除非这样更好? –

+0

不,不要在注释中张贴多行Python代码,因为缩进会丢失。但无论如何,你的代码属于问题本身,评论只是为了帮助你澄清和改进你的问题。 –

回答

1

下面是结合my old code一些新的代码来执行逆操作的程序。

您的inv_get_digit函数中出现语法错误:您将冒号从elif行的末尾离开。而且不需要做str(c),因为c已经是一个字符串了。

恐怕你的decode功能没有多大意义。它应该将一个字符串作为输入并返回一个整数。请参阅下面的工作版本。

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) 

print('Testing get_digit') 
digits = ''.join([get_digit(d) for d in range(64)]) 
print(digits) 

def inv_get_digit(c): 
    if '0' <= c <= '9': 
     d = ord(c) - 48 
    elif 'A' <= c <= 'Z': 
     d = ord(c) - 55 
    elif 'a' <= c <= 'z': 
     d = ord(c) - 61 
    elif c == '-': 
     d = 62 
    elif c == '+': 
     d = 63 
    else: 
     raise ValueError('Invalid input: ' + c) 
    return d 

print('\nTesting inv_get_digit') 
nums = [inv_get_digit(c) for c in digits] 
print(nums == list(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) 

print('\nTesting encode') 
numdata = (0,, 68719476735) 
strdata = [] 
for i in numdata: 
    s = encode(i) 
    print(i, s) 
    strdata.append(s) 

def decode(s): 
    out = [] 
    n = 0 
    for c in reversed(s): 
     d = inv_get_digit(c) 
     n = 64 * n + d 
    return n 

print('\nTesting decode') 
for s, oldn in zip(strdata, numdata): 
    n = decode(s) 
    print(s, n, n == oldn) 

输出

Testing get_digit 
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+ 

Testing inv_get_digit 
True 

Testing encode 
0 000000 
gR1iC9 
68719476735 ++++++ 

Testing decode 
000000 0 True 
gR1iCTrue 
++++++ 68719476735 True 
+0

啊,再一次,谢谢。一个简单的问题,为什么我们必须用's'作为参数? –

+1

@JustAMathematician无后顾之忧。我们可以称之为'decode'的任何我们喜欢的参数。我只是用's',因为它是“字符串”的助记符,我懒得想出一个更有意义的名字。 ;)同样,我使用'c'作为char,'d'作为数字。一般来说,使用更长的描述性名称是一个好主意,但在明显发生的情况下使用短名称也可以。当然,对于作者来说,显而易见的东西对于读者来说并不总是很明显。 ;) –