Conversione in base 62


90

Come convertiresti un numero intero in base 62 (come esadecimale, ma con queste cifre: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').

Ho cercato di trovare una buona libreria Python per questo, ma sembrano tutti occupati con la conversione di stringhe. Il modulo Python base64 accetta solo stringhe e trasforma una singola cifra in quattro caratteri. Stavo cercando qualcosa di simile a quello che usano gli accorciatori di URL.


Sembra che qualcuno abbia appena trovato un'idea di progetto open source :) Fammi sapere se trovi qualcosa o decidi di crearne una tua ...
samoz

Se desideri creare URL brevi, potresti voler utilizzare l'intero set di caratteri che non devono essere codificati: en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters . Sono 66 caratteri.
l0b0

Penso che passerò il punto e la tilde, solo per evitare confusione dell'utente, ma il trattino e le sottolineature dovrebbero essere aggiunte utili, grazie.
mikl

che dire di Base64? Potresti avere più fortuna a trovare biblioteche per questo.
Mike Cooper

Questa domanda ha una serie di risposte applicabili: stackoverflow.com/questions/561486/…
Miles

Risposte:


166

Non esiste un modulo standard per questo, ma ho scritto le mie funzioni per ottenerlo.

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def encode(num, alphabet):
    """Encode a positive number into Base X and return the string.

    Arguments:
    - `num`: The number to encode
    - `alphabet`: The alphabet to use for encoding
    """
    if num == 0:
        return alphabet[0]
    arr = []
    arr_append = arr.append  # Extract bound-method for faster access.
    _divmod = divmod  # Access to locals is faster.
    base = len(alphabet)
    while num:
        num, rem = _divmod(num, base)
        arr_append(alphabet[rem])
    arr.reverse()
    return ''.join(arr)

def decode(string, alphabet=BASE62):
    """Decode a Base X encoded string into the number

    Arguments:
    - `string`: The encoded string
    - `alphabet`: The alphabet to use for decoding
    """
    base = len(alphabet)
    strlen = len(string)
    num = 0

    idx = 0
    for char in string:
        power = (strlen - (idx + 1))
        num += alphabet.index(char) * (base ** power)
        idx += 1

    return num

Nota il fatto che puoi dargli qualsiasi alfabeto da usare per la codifica e la decodifica. Se tralasci l' alphabetargomento, otterrai l'alfabeto di 62 caratteri definito sulla prima riga di codice, e quindi la codifica / decodifica dalla / alla 62 base.

Spero che questo ti aiuti.

PS - Per gli accorciatori di URL, ho scoperto che è meglio tralasciare alcuni caratteri confusi come 0Ol1oI ecc. Quindi uso questo alfabeto per le mie esigenze di accorciamento degli URL - "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

Divertiti.


5
+1: Bello! Questo può essere esteso con più caratteri compatibili con gli URL per salvare eventualmente un carattere qua e là. I personaggi che so essere al sicuro sono: $-_.+!*'(),;/?:@&= Probabilmente puoi usare anche altri personaggi come []~ecc.
Blixt

24
Bug di denominazione: non è la base 62, poiché l'alfabeto è personalizzabile.
rilassarsi il

3
Per la decodifica, è una buona abitudine non calcolare le potenze (fa risparmiare tempo, è più breve da scrivere, ma soprattutto evita errori off-by-one), quindi: num = 0; for char in string: num = num * base + alphabet.index (char)
ShreevatsaR

1
@ ShreevatsaR: qualche motivo particolare per usare str.index () invece di una ricerca nel dizionario? Vedi la mia risposta ...
John Machin

2
Jonathan - Python in grado di gestire i numeri di lunghezza arbitraria - non c'è overflow: >>> 256 * (62 ** 100) 44402652562862911414971048359760030835982580330786570771137804709455598239929932673552190201125730101070867075377228748911717860448985185350731601887476350502973424822800696272224256L
Anthony Briggs

53

Una volta ho scritto una sceneggiatura anche per questo, penso che sia abbastanza elegante :)

import string
# Remove the `_@` below for base62, now it has 64 characters
BASE_LIST = string.digits + string.letters + '_@'
BASE_DICT = dict((c, i) for i, c in enumerate(BASE_LIST))

def base_decode(string, reverse_base=BASE_DICT):
    length = len(reverse_base)
    ret = 0
    for i, c in enumerate(string[::-1]):
        ret += (length ** i) * reverse_base[c]

    return ret

def base_encode(integer, base=BASE_LIST):
    if integer == 0:
        return base[0]

    length = len(base)
    ret = ''
    while integer != 0:
        ret = base[integer % length] + ret
        integer /= length

    return ret

Utilizzo di esempio:

for i in range(100):                                    
    print i, base_decode(base_encode(i)), base_encode(i)

9
Questa versione è notevolmente più veloce della soluzione accettata da Baishampayan. Ho ottimizzato ulteriormente calcolando la lunghezza al di fuori della funzione. Risultati dei test (100.000 iterazioni): version-WoLpH: .403 .399 .399 .398 .398 | versione-Baishampayan: 1.783 1.785 1.782 1.788 1.784. Questa versione è circa 4 volte più veloce.
Jordan

se si usa reversed(string)più velocemente dello slicing string[::-1]nella funzione base_decode.
ENDOH takanao

1
Mi ci è voluto molto tempo per trovare questa domanda. Non ho mai saputo che questa fosse chiamata conversione base62. Bella risposta.

Ho dovuto cambiare integer /= lengthper integer //=lengthottenere il resto corretto
karlgold il

10

Il seguente decoder-maker funziona con qualsiasi base ragionevole, ha un ciclo molto più ordinato e fornisce un messaggio di errore esplicito quando incontra un carattere non valido.

def base_n_decoder(alphabet):
    """Return a decoder for a base-n encoded string
    Argument:
    - `alphabet`: The alphabet used for encoding
    """
    base = len(alphabet)
    char_value = dict(((c, v) for v, c in enumerate(alphabet)))
    def f(string):
        num = 0
        try:
            for char in string:
                num = num * base + char_value[char]
        except KeyError:
            raise ValueError('Unexpected character %r' % char)
        return num
    return f

if __name__ == "__main__":
    func = base_n_decoder('0123456789abcdef')
    for test in ('0', 'f', '2020', 'ffff', 'abqdef'):
        print test
        print func(test)

Anche se probabilmente non lo userei mai, anch'io ti ho dato un pollice in alto per la creatività. Questo codice mi ha fatto ridere. :)
Sepero

@Sepero: cosa c'è di così divertente? È un software serio, robusto e industriale. Nessun Micky-Mouse che inverte con un **operatore nel ciclo.
John Machin

Calmati amico. Hai ragione. Mi mancava la vera bontà del tuo ciclo interiore perché è sepolto all'interno di cose non correlate alla domanda (wrapping, controllo degli errori, test di unità).
Sepero

Sembra buono, ma non hai dimenticato un codificatore "industriale" che richiede un numero intero più un alfabeto per produrre una stringa?
martineau

1
La q nell'ultimo valore era intenzionale per mostrare l'eccezione ValueError sollevata?
Thomas Vander Stichele

7

Se stai cercando la massima efficienza (come django), ti consigliamo qualcosa come il seguente. Questo codice è una combinazione di metodi efficienti di Baishampayan Ghose, WoLpH e John Machin.

# Edit this list of characters as desired.
BASE_ALPH = tuple("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_ALPH))
BASE_LEN = len(BASE_ALPH)

def base_decode(string):
    num = 0
    for char in string:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def base_encode(num):
    if not num:
        return BASE_ALPH[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding = BASE_ALPH[rem] + encoding
    return encoding

Puoi anche calcolare il tuo dizionario in anticipo. (Nota: la codifica con una stringa mostra una maggiore efficienza rispetto a un elenco, anche con numeri molto lunghi.)

>>> timeit.timeit("for i in xrange(1000000): base.base_decode(base.base_encode(i))", setup="import base", number=1)
2.3302059173583984

1 milione di numeri codificati e decodificati in meno di 2,5 secondi. (2.2 Ghz i7-2670QM)


Non è necessariamente necessario il tuple()giro BASE_ALPHall'inizio. In Python ogni stringa è iterabile. Questa caratteristica è ovviamente sfruttata da enumerate(). Quindi il codice diventa ancora più snello :)
Luis Nell

6
Ehi origiNell, hai ragione sul fatto che tuple () non è necessaria, ma sul mio sistema rende il codice più veloce del 20% circa. Prova a provarlo senza tuple () e vedi cosa funziona meglio per te. Saluti :)
Sepero

Punto interessante. Ha perfettamente senso poiché le tuple sono più leggere delle stringhe. Grazie per l'illuminazione :)!
Luis Nell

@Sepero Ho ulteriormente migliorato la tua versione in termini di formattazione, denominazione, test e funzionalità (i numeri negativi sono supportati): pastebin.com/4uket7iu (puoi aggiornare la tua risposta con questo)
Joschua

@Joschua - Il tuo codice sul tuo URL non ha funzionato per me. base_encode () sembrava generare solo una cifra codificata per i numeri che ho testato.
SMGreenfield

4

Se usi il framework django, puoi usare il modulo django.utils.baseconv.

>>> from django.utils import baseconv
>>> baseconv.base62.encode(1234567890)
1LY7VK

Oltre a base62, baseconv ha definito anche base2 / base16 / base36 / base56 / base64.


3

Probabilmente vuoi base64, non base62. C'è una versione compatibile con l'URL che fluttua in giro, quindi i due caratteri di riempimento extra non dovrebbero essere un problema.

Il processo è abbastanza semplice; si consideri che base64 rappresenta 6 bit e un byte regolare rappresenta 8. Assegnare un valore da 000000 a 111111 a ciascuno dei 64 caratteri scelti e unire i 4 valori insieme per far corrispondere un set di 3 base256 byte. Ripeti per ogni set di 3 byte, riempiendo alla fine con la tua scelta di caratteri di riempimento (0 è generalmente utile).


5
I metodi di codifica base64 standard di Python non sono realmente adatti per URL brevi, poiché è ottimizzato per la codifica di byte (cioè stringhe / lettere) e produrrà output più lunghi rispetto al semplice spostamento di base del valore numerico.
mikl

@mikl Ovviamente, il modulo base64 di Python potrebbe non essere adatto per generare URL brevi, ma tutti i metodi di codifica di Python funzionano davvero su sequenze numeriche in base 256. i byte sono veramente "stringhe" codificate in base 256. Python 2.x tratta le stringhe come una sequenza di byte, mentre Python 3.x (che fa la cosa giusta) tratta le stringhe come Unicode. Quindi b'foobar 'è in realtà solo un modo elegante di scrivere [102, 111, 111, 98, 97, 114] o [0x66,0x6f, 0x6f, 0x62,0x61,0x72] o b' \ x66 \ x6f \ x6f \ x62 \ x61 \ x72 'che non sorprende è la rappresentazione in base 256. I byte non sono stringhe o lettere. I byte sono byte. =)
yesudeep

@yesudeep: Quindi, i byte sono byte ... e qual è esattamente il tuo punto?
martineau

3

Se tutto ciò di cui hai bisogno è generare un ID breve (dal momento che menzioni accorciatori di URL) piuttosto che codificare / decodificare qualcosa, questo modulo potrebbe aiutare:

https://github.com/stochastic-technologies/shortuuid/


Non sono sicuro che sia appropriato per URL brevi. Un UUID è di solito un numero molto grande, quindi anche la codifica base57 come fa è destinato ad essere piuttosto lungo per un URL breve.
mikl

Puoi semplicemente tagliare quanto vuoi, le collisioni saranno ancora improbabili in quanto puramente casuali, ma non saranno più un ID univoco.
Stavros Korokithakis

2

puoi scaricare il modulo zbase62 da pypi

per esempio

>>> import zbase62
>>> zbase62.b2a("abcd")
'1mZPsa'

2
Sì, l'ho visto prima, ma converte le stringhe, non i numeri :)
mikl

2

Ho tratto grandi benefici dai post degli altri qui. Inizialmente avevo bisogno del codice python per un progetto Django, ma da allora sono passato a node.js, quindi ecco una versione javascript del codice (la parte di codifica) fornita da Baishampayan Ghose.

var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

function base62_encode(n, alpha) {
  var num = n || 0;
  var alphabet = alpha || ALPHABET;

  if (num == 0) return alphabet[0];
  var arr = [];
  var base = alphabet.length;

  while(num) {
    rem = num % base;
    num = (num - rem)/base;
    arr.push(alphabet.substring(rem,rem+1));
  }

  return arr.reverse().join('');
}

console.log(base62_encode(2390687438976, "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"));

Ho aggiornato questo codice e l'ho trasformato in un progetto open source per chiunque sia interessato github.com/sbussard/encode-the-things
Stephen

2

Spero che il seguente frammento possa aiutare.

def num2sym(num, sym, join_symbol=''):
    if num == 0:
        return sym[0]
    if num < 0 or type(num) not in (int, long):
        raise ValueError('num must be positive integer')

    l = len(sym)  # target number base
    r = []
    div = num
    while div != 0: # base conversion
        div, mod = divmod(div, l)
        r.append(sym[mod])

    return join_symbol.join([x for x in reversed(r)])

Utilizzo per il tuo caso:

number = 367891
alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
print num2sym(number, alphabet)  # will print '1xHJ'

Ovviamente, puoi specificare un altro alfabeto, composto da un numero maggiore o minore di simboli, quindi convertirà il tuo numero nella base numerica minore o maggiore. Ad esempio, se si specifica "01" come alfabeto, verrà emessa una stringa che rappresenta il numero di input come binario.

Puoi mescolare l'alfabeto inizialmente per avere la tua rappresentazione unica dei numeri. Può essere utile se stai creando un servizio di abbreviazione di URL.


1
Non male. Potresti voler usare if num < 0 or type(num) not in (int, long):.
martineau

È meglio, ma è un po 'più complicato perché longnon esiste in Py 3.x, quindi si potrebbe voler usare questa risposta .
martineau

1
O usare la mia versione portatile: isinstance(x, (type(1), type(2**32))).
martineau

2

Ora c'è una libreria Python per questo.

Sto lavorando alla creazione di un pacchetto pip per questo.

Ti consiglio di usare il mio bases.py https://github.com/kamijoutouma/bases.py che è stato ispirato da bases.js

from bases import Bases
bases = Bases()

bases.toBase16(200)                // => 'c8'
bases.toBase(200, 16)              // => 'c8'
bases.toBase62(99999)              // => 'q0T'
bases.toBase(200, 62)              // => 'q0T'
bases.toAlphabet(300, 'aAbBcC')    // => 'Abba'

bases.fromBase16('c8')               // => 200
bases.fromBase('c8', 16)             // => 200
bases.fromBase62('q0T')              // => 99999
bases.fromBase('q0T', 62)            // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300

fare riferimento a https://github.com/kamijoutouma/bases.py#known-basesalphabets per sapere quali basi sono utilizzabili


2

Ecco la mia soluzione:

def base62(a):
    baseit = (lambda a=a, b=62: (not a) and '0' or
        baseit(a-a%b, b*62) + '0123456789abcdefghijklmnopqrstuvwxyz'
                              'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[a%b%61 or -1*bool(a%b)])
    return baseit()

spiegazione

In qualsiasi base ogni numero è uguale a a1+a2*base**2+a3*base**3...Quindi l'obiettivo è trovare tutte le as.

Per ogni N=1,2,3...il codice isola il aN*base**N"modulo" bper b=base**(N+1)cui divide tutti gli as più grandi di Ne affetta tutti gli as in modo che il loro numero di serie sia minore di Ndecrescente aogni volta che la funzione viene chiamata ricorsivamente dalla corrente aN*base**N.

Base%(base-1)==1quindi base**p%(base-1)==1e quindi q*base^p%(base-1)==qcon una sola eccezione, quando q==base-1che ritorna 0. Per risolvere quel caso, ritorna 0. La funzione controlla 0dall'inizio.


vantaggi

In questo esempio c'è solo una moltiplicazione (invece di una divisione) e alcune operazioni di modulo, che sono tutte relativamente veloci.


1

Personalmente mi piace la soluzione di Baishampayan, soprattutto per aver messo a nudo i personaggi confusi.

Per completezza e soluzione con prestazioni migliori, questo post mostra un modo per utilizzare il modulo Python base64.


1
Come accennato nel mio commento a Williham Totland, Pythons base64 non è ottimale per la codifica dei numeri, poiché è ottimizzato per le stringhe.
mikl

1

L'ho scritto tempo fa e ha funzionato abbastanza bene (negativi e tutto incluso)

def code(number,base):
    try:
        int(number),int(base)
    except ValueError:
        raise ValueError('code(number,base): number and base must be in base10')
    else:
        number,base = int(number),int(base)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = [0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f","g","h","i","j",
               "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y",
               "z","A","B","C","D","E","F","G","H","I","J","K","L","M","N",
               "O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    final = ""
    loc = 0
    if number < 0:
        final = "-"
        number = abs(number)
    while base**loc <= number:
        loc = loc + 1
    for x in range(loc-1,-1,-1):
        for y in range(base-1,-1,-1):
            if y*(base**x) <= number:
                final = "{}{}".format(final,numbers[y])
                number = number - y*(base**x)
                break
    return final

def decode(number,base):
    try:
        int(base)
    except ValueError:
        raise ValueError('decode(value,base): base must be in base10')
    else:
        base = int(base)
    number = str(number)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f",
               "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
               "w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L",
               "M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    final = 0
    if number.startswith("-"):
        neg = True
        number = list(number)
        del(number[0])
        temp = number
        number = ""
        for x in temp:
            number = "{}{}".format(number,x)
    else:
        neg = False
    loc = len(number)-1
    number = str(number)
    for x in number:
        if numbers.index(x) > base:
            raise ValueError('{} is out of base{} range'.format(x,str(base)))
        final = final+(numbers.index(x)*(base**loc))
        loc = loc - 1
    if neg:
        return -final
    else:
        return final

mi dispiace per la durata di tutto questo


1
BASE_LIST = tuple("23456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_LIST))
BASE_LEN = len(BASE_LIST)

def nice_decode(str):
    num = 0
    for char in str[::-1]:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def nice_encode(num):
    if not num:
        return BASE_LIST[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding += BASE_LIST[rem]
    return encoding

1
Questo risolve il nome di BASE_LIST e inverte anche la stringa sulla decodifica che era stata omessa nella risposta altrimenti eccellente di Spero
paulkav1

1

Ecco un modo ricorrente e iterativo per farlo. Quello iterativo è un po 'più veloce a seconda del conteggio dell'esecuzione.

def base62_encode_r(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    return s[dec] if dec < 62 else base62_encode_r(dec / 62) + s[dec % 62]
print base62_encode_r(2347878234)

def base62_encode_i(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = ''
    while dec > 0:
        ret = s[dec % 62] + ret
        dec /= 62
    return ret
print base62_encode_i(2347878234)

def base62_decode_r(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if len(b62) == 1:
        return s.index(b62)
    x = base62_decode_r(b62[:-1]) * 62 + s.index(b62[-1:]) % 62
    return x
print base62_decode_r("2yTsnM")

def base62_decode_i(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = 0
    for i in xrange(len(b62)-1,-1,-1):
        ret = ret + s.index(b62[i]) * (62**(len(b62)-i-1))
    return ret
print base62_decode_i("2yTsnM")

if __name__ == '__main__':
    import timeit
    print(timeit.timeit(stmt="base62_encode_r(2347878234)", setup="from __main__ import base62_encode_r", number=100000))
    print(timeit.timeit(stmt="base62_encode_i(2347878234)", setup="from __main__ import base62_encode_i", number=100000))
    print(timeit.timeit(stmt="base62_decode_r('2yTsnM')", setup="from __main__ import base62_decode_r", number=100000))
    print(timeit.timeit(stmt="base62_decode_i('2yTsnM')", setup="from __main__ import base62_decode_i", number=100000))

0.270266867033
0.260915645986
0.344734796766
0.311662500262

Mi è piaciuto molto il tuo approccio ricorsivo. Mia figlia, che stava prendendo AP Comp Sci, aveva escogitato questa stessa soluzione per me per implementare un "base25" (usando 'ABCDEFHJKMNPQRTUVWXY34789') in C ++. Sono andato a convertirlo in Python ed essendo un principiante totale con quel linguaggio ho incontrato alcuni ostacoli - che hai risolto elegantemente in una singola riga di codice! Eviti anche un problema comune con 0 che si traduce in una stringa vuota in alfabeti che non iniziano con 0-9. Ottimo lavoro! (Non ho bisogno di numeri negativi, ma il tuo approccio è stato così buono che potrebbe essere bello aggiungerlo per i browser futuri)
SMGreenfield

1

Pitone 3.7.x

Ho trovato un GitHub di dottorato per alcuni algoritmi durante la ricerca di uno script base62 esistente . Non funzionava per l'attuale versione max di Python 3 in questo momento, quindi sono andato avanti e ho risolto dove necessario e ho fatto un piccolo refactoring. Di solito non lavoro con Python e l'ho sempre usato ad hoc, quindi YMMV. Tutto il merito va al Dr. Zhihua Lai . Ho appena risolto i problemi per questa versione di Python.

file base62.py

#modified from Dr. Zhihua Lai's original on GitHub
from math import floor
base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
b = 62;
def toBase10(b62: str) -> int:
    limit = len(b62)
    res = 0
    for i in range(limit):
        res = b * res + base.find(b62[i])
    return res
def toBase62(b10: int) -> str:
    if b <= 0 or b > 62:
        return 0
    r = b10 % b
    res = base[r];
    q = floor(b10 / b)
    while q:
        r = q % b
        q = floor(q / b)
        res = base[int(r)] + res
    return res

file try_base62.py

import base62
print("Base10 ==> Base62")
for i in range(999):
    print(f'{i} => {base62.toBase62(i)}')
base62_samples = ["gud", "GA", "mE", "lo", "lz", "OMFGWTFLMFAOENCODING"]
print("Base62 ==> Base10")
for i in range(len(base62_samples)):
    print(f'{base62_samples[i]} => {base62.toBase10(base62_samples[i])}')

uscita di try_base62.py

Base10 ==> Base62
0 => 0
[...]
998 => g6
Base62 ==> Base10
gud => 63377
GA => 2640
mE => 1404
lo => 1326
lz => 1337
OMFGWTFLMFAOENCODING => 577002768656147353068189971419611424

Poiché non c'erano informazioni sulla licenza nel repository, ho inviato un PR in modo che l'autore originale sappia almeno che altre persone stanno usando e modificando il loro codice.


0

Mi spiace, non posso aiutarti con una libreria qui. Preferirei usare base64 e aggiungere solo caratteri extra a tua scelta, se possibile!

Quindi puoi usare il modulo base64.

Se questo è davvero, davvero non possibile:

Puoi farlo da solo in questo modo (questo è pseudo-codice):

base62vals = []
myBase = 62
while num > 0:
   reminder = num % myBase
   num = num / myBase
   base62vals.insert(0, reminder)

0

con semplice ricorsione

"""
This module contains functions to transform a number to string and vice-versa
"""
BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
LEN_BASE = len(BASE)


def encode(num):
    """
    This function encodes the given number into alpha numeric string
    """

    if num < LEN_BASE:
        return BASE[num]

    return BASE[num % LEN_BASE] + encode(num//LEN_BASE)


def decode_recursive(string, index):
    """
    recursive util function for decode
    """

    if not string or index >= len(string):
        return 0

    return (BASE.index(string[index]) * LEN_BASE ** index) + decode_recursive(string, index + 1)


def decode(string):
    """
    This function decodes given string to number
    """

    return decode_recursive(string, 0)

0

Il più semplice in assoluto.

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def encode_base62(num):
    s = ""
    while num>0:
      num,r = divmod(num,62)
      s = BASE62[r]+s
    return s


def decode_base62(num):
   x,s = 1,0
   for i in range(len(num)-1,-1,-1):
      s = int(BASE62.index(num[i])) *x + s
      x*=62
   return s

print(encode_base62(123))
print(decode_base62("1Z"))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.