2009-07-25 6 views
25

Jak mogę zakodować liczbę całkowitą z base 36 w Pythonie, a następnie ją odszyfrować?Python base 36 encoding

+0

możliwe duplikat [Jak przekonwertować liczbę całkowitą do najkrótszej url bezpieczny ciąg w języku Python?] (http://stackoverflow.com/questions/561486/how-to-convert-an-integer-to-tort-url-safe-string-in-python) – Belldandu

Odpowiedz

32

Czy próbowałeś próbnego kodu Wikipedii?

def base36encode(number, alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ'): 
    """Converts an integer to a base36 string.""" 
    if not isinstance(number, (int, long)): 
     raise TypeError('number must be an integer') 

    base36 = '' 
    sign = '' 

    if number < 0: 
     sign = '-' 
     number = -number 

    if 0 <= number < len(alphabet): 
     return sign + alphabet[number] 

    while number != 0: 
     number, i = divmod(number, len(alphabet)) 
     base36 = alphabet[i] + base36 

    return sign + base36 

def base36decode(number): 
    return int(number, 36) 

print base36encode(1412823931503067241) 
print base36decode('AQF8AA0006EH') 
+18

Chrystus, jeśli mogą to zrobić -> int w dowolnej bazie, można by pomyśleć, że pozwoliłoby ci zrobić int-> str w dowolnej bazie z wbudowanym ... – Dubslow

+4

, aby uczynić go jeszcze bardziej pytonicznym, dodać import 'string' i zastąpić wartość alfabetu z' string.digits + string.lowercase' – DataGreed

+1

interfejs pomiędzy 'base36encode' a' base36decode' jest uszkodzony, ten ostatni zawiedzie (prawdopodobnie dyskretnie), aby zdekodować coś zakodowanego w z niestandardowym argumentem "alfabet" – Grozz

31

Chciałbym przeczytać to wcześniej. Oto odpowiedź:

def base36encode(number): 
    if not isinstance(number, (int, long)): 
     raise TypeError('number must be an integer') 
    if number < 0: 
     raise ValueError('number must be positive') 

    alphabet, base36 = ['ABCDEFGHIJKLMNOPQRSTUVWXYZ', ''] 

    while number: 
     number, i = divmod(number, 36) 
     base36 = alphabet[i] + base36 

    return base36 or alphabet[0] 


def base36decode(number): 
    return int(number, 36) 

print(base36encode(1412823931503067241)) 
print(base36decode('AQF8AA0006EH')) 
+4

Aby zawrzeć małe litery, zobacz [Jak przekonwertować liczbę całkowitą na najkrótszy ciąg znaków URL w języku Python?] (Http://stackoverflow.com/questions/561486/how-to-convert-an-integer-to-the- najkrótszy-url-safe-string-in-python/561704 # 561704) –

+0

@Tadeck: Ponieważ musisz odwrócić 'base36' zanim go zwrócisz. –

+0

@JohnY: Mój błąd, to nie to samo. – Tadeck

9

straszna odpowiedź, ale po prostu bawiłem się tą myślą, którą chciałbym się podzielić.

import string, math 

int2base = lambda a, b: ''.join(
    [(string.digits + string.lowercase + string.uppercase)[(a/b**i)%b] 
    for i in xrange(int(math.log(a, b)), -1, -1)] 
    ) 

num = 1412823931503067241 
test = int2base(num, 36) 
test2 = int(test, 36) 
print test2 == num 
+0

Podoba mi się to trochę, ale być może mam słabość do krótszego kodu. –

+4

Funkcja math.log zwraca zmiennoprzecinkowe ograniczenie o ograniczonej precyzji, a więc zaokrągla do 14 cyfr przed obcięciem części ułamkowej. Pozwala to na przykład uniknąć 5.999999999999999 do 5.0. –

+1

Funkcja math.log() kończy się niepowodzeniem, gdy a == 0 i mimo to jest zasysana. –

2

Działa to, jeśli zależy Ci tylko na dodatnich liczbach całkowitych.

def int_to_base36(num): 
    """Converts a positive integer into a base36 string.""" 
    assert num >= 0 
    digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 

    res = '' 
    while not res or num > 0: 
     num, i = divmod(num, 36) 
     res = digits[i] + res 
    return res 

Aby przekonwertować z powrotem na int, po prostu użyj int(num, 36). Przez konwersję dowolnych baz zobaczyć https://gist.github.com/mbarkhau/1b918cb3b4a2bdaf841c

11
from numpy import base_repr 

num = base_repr(num, 36) 
num = int(num, 36) 

Oto informacje o numpy.

+0

Podjęłam próbę poprawy tej odpowiedzi, umożliwiając jej uruchamianie za pomocą przykładowych danych i dodawanie kolejnych zasobów dokumentacji. Zmiana została z jakiegoś powodu odrzucona z wyjaśnieniem, że była bardziej odpowiednia jako własna odpowiedź. Dlatego dodałem poprawioną wersję Twojej odpowiedzi poniżej: http://stackoverflow.com/questions/1181919/python-base-36-encoding/42331616#42331616 –

5

Można użyć https://github.com/tonyseek/python-base36.

$ pip install base36 

a następnie

>>> import base36 
>>> assert base36.dumps(19930503) == 'bv6h3' 
>>> assert base36.loads('bv6h3') == 19930503 
+1

To jest odpowiednia odpowiedź. Nie wiem, dlaczego wszyscy chcą wymyślić koło. –

+0

@MichaelScheper Ponieważ zależności są trudne. Zobacz 'lewy klawisz'. Skopiowanie i wklejenie funkcji trywialnej do pliku, który robi to, co chcesz, jest czasem lepsze niż dodanie nowej zależności zewnętrznej. – mbarkhau

+1

@mbarkhau Możesz pobrać trzecie zależności od swojego dostawcy repozytorium lub prywatnego PyPI mirror (tak jak projekty Golang). Może to być lepsze niż kopiowanie i wklejanie fragmentów kodu, dla oddzielnego pokrycia testowego i planu zwolnienia. –

4

Można użyć numpy na base_repr(...) do tego.

import numpy as np 

num = 2017 

num = np.base_repr(num, 36) 
print(num) # 1K1 

num = int(num, 36) 
print(num) # 2017 

Oto kilka informacji o numpy, int(x, base=10) i np.base_repr(number, base=2, padding=0).

(Ta odpowiedź została pierwotnie przedstawiony jako edytuje odpowiedź @ Christopher-Beland, ale został odrzucony na rzecz własnej odpowiedzi.)

Powiązane problemy