2017-10-15 4 views
2

Donc, j'essaye d'écrire un programme pour décoder des nombres de base 64 de 6 caractères.Conversion d'une chaîne en un nombre

Voici l'énoncé du problème:

Retour le numéro 36 bits représenté en nombre de base 64 dans l'ordre inverse par la chaîne de 6 caractères s où l'ordre des 64 chiffres est:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz- +

-à-dire

decode ('000000') → 0

decode ('gR1iC9') →

decode ('++++++') → 68719476735

je voudrais faire sans cordes.

La meilleure façon de le faire serait de créer l'inverse de la fonction suivante:

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)) 

Sortie

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

Ce qui est en fait de PM 2Ring sur this page.

Comment écrire l'inverse de ce programme?

Un début:

L'inverse de get_digits comme ci-dessus est ci-dessous:

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

S'il vous plaît essayer d'écrire un code vous-même. Comme je l'ai dit [ici] (https://stackoverflow.com/questions/46739875/converting-a-number-to-base-64-in-python/46740374#comment80448645_46740374), la première étape est d'inverser 'get_digit', et je vous ai donné un indice sur la façon de le faire. –

+0

J'ai modifié mon message pour refléter votre commentaire. Je n'ai pas publié le nouveau code dans les commentaires car le format est faussé. À moins que ce soit mieux comme ça? –

+0

Non, ne publiez jamais de code Python multi-ligne dans les commentaires car l'indentation est perdue.Mais de toute façon, votre code appartient au corps même de la question, les commentaires sont juste pour vous aider à clarifier et améliorer votre question. –

Répondre

1

Voici un programme qui combine my old code avec un nouveau code pour effectuer les opérations inverses.

Vous avez une erreur de syntaxe dans votre fonction inv_get_digit: vous avez quitté le signe deux-points à la fin d'une ligne elif. Et il n'y a pas besoin de faire str(c), puisque c est déjà une chaîne. Je crains que votre fonction n'a pas beaucoup de sens. Il est supposé prendre une chaîne en entrée et renvoyer un entier. S'il vous plaît voir une version de travail ci-dessous.

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) 

sortie

Testing get_digit 
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+ 

Testing inv_get_digit 
True 

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

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

Ahh encore une fois, merci. Une question simple, pourquoi devons-nous utiliser 's' comme argument? –

+1

@JustAMathematician Pas de soucis. Nous pourrions appeler l'argument de «décoder» tout ce que nous aimons. J'ai juste utilisé 's' parce que c'est un mnémonique pour" chaîne ", et j'étais trop paresseux pour trouver un nom plus significatif. ;) De même, j'ai utilisé 'c' pour char, et' d' pour digit. Généralement, c'est une bonne idée d'utiliser des noms plus descriptifs, mais il peut être correct d'utiliser des noms courts quand il est évident que ce qui se passe. Bien sûr, ce qui est évident pour l'auteur n'est pas toujours évident pour le lecteur. ;) –