Перетворення бази 62


92

Як би ви перетворили ціле число на базу 62 (як шістнадцяткову, але з цими цифрами: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').

Я намагався знайти для нього хорошу бібліотеку Python, але, схоже, вони всі зайняті перетворенням рядків. Модуль Python base64 приймає лише рядки і перетворює одну цифру на чотири символи. Я шукав щось подібне до того, що використовують скорочувачі URL.


Здається, хтось щойно знайшов ідею проекту з відкритим кодом :) Повідомте мене, якщо ви щось знайдете або вирішите створити власний ...
самоз

Якщо ви хочете створити короткі URL-адреси, ви можете використати весь набір символів, які не потребують кодування: en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters . Це 66 символів.
l0b0

Думаю, я передам крапку і тильду, щоб уникнути плутанини користувачів, але тире та підкреслення повинні бути вартими доповненнями, дякую.
mikl

як щодо Base64? Можливо, вам пощастить знайти бібліотеки для цього.
Mike Cooper

Це запитання має ряд застосовних відповідей: stackoverflow.com/questions/561486/…
Майлз

Відповіді:


169

Для цього не існує стандартного модуля, але для цього я написав власні функції.

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

Зверніть увагу на те, що ви можете надати йому будь-який алфавіт для кодування та декодування. Якщо alphabetаргумент залишити поза увагою, ви отримаєте 62-значний алфавіт, визначений у першому рядку коду, а отже, кодування / декодування до / з 62 бази.

Сподіваюся, це допомагає.

PS - Для скорочувачів URL-адрес я виявив, що краще не брати до уваги кілька заплутаних символів, таких як 0Ol1oI і т. Д. Таким чином, я використовую цей алфавіт для своїх потреб у скороченні URL-адрес - "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

Веселіться.


5
+1: Приємно! Це можна розширити за допомогою більш зручних для URL-адрес символів, щоб можливо зберегти один символ тут і там. Персонажі, яких я знаю, є безпечними: $-_.+!*'(),;/?:@&= Ви, напевно, можете використовувати деякі інші символи, подібні []~тощо.
Blixt

24
Помилка іменування: це не база 62, оскільки алфавіт можна налаштувати.
розслабтесь

3
Для декодування кращою звичкою є не обчислювати потужності (економить час, коротше пише, але, що важливіше, уникає поодиноких помилок), таким чином: num = 0; для символу в рядку: num = num * base + alphabet.index (char)
ShreevatsaR

1
@ShreevatsaR: якась конкретна причина використання str.index () замість пошуку словника? Дивіться мою відповідь ...
Джон Мачин,

2
Джонатан - Python може обробляти числа довільної довжини - немає переповнення: >>> 256 * (62 ** 100) 44402652562862911414971048359760030835982580330786570771137804709455598239929932673552190201125730101070867075377228748911717860448985185350731601887476350502973424822800696272224256L
Ентоні Бріггс

53

Одного разу я написав сценарій, щоб зробити це теж, я думаю, це досить елегантно :)

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

Приклад використання:

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

9
Ця версія значно швидша, ніж прийняте рішення Байшампаяна. Я оптимізував далі, обчислюючи довжину поза функцією. Результати тестування (100 000 ітерацій): version-WoLpH: .403 .399 .399 .398 .398 | версія-Байшампаян: 1,783 1,785 1,782 1,788 1,784. Ця версія приблизно в чотири рази швидша.
Йорданія

якщо використовувати reversed(string)швидше, ніж нарізання string[::-1]у функції base_decode.
ENDOH takanao

1
Мені знадобилося багато часу, щоб знайти це питання. Ніколи не знав, що це називається перетворенням base62. Приємна відповідь.

1
Мені довелося перейти integer /= lengthна, integer //=lengthщоб отримати правильний залишок
karlgold

10

Наступний виробник декодерів працює з будь-якою розумною базою, має набагато акуратніший цикл і видає явне повідомлення про помилку, коли зустрічає недійсний символ.

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)

Хоча я, мабуть, ніколи б цим не користувався, я теж підніс вам великі пальці для творчості. Цей код дав мені сміятися. :)
Sepero

@Sepero: Що такого смішного? Це серйозне надійне програмне забезпечення промислової потужності. Немає реверсу Міккі-Мауса з **оператором у циклі.
John Machin

Заспокойся, друг. Ти маєш рацію. Я пропустив справжню якість вашого внутрішнього циклу через те, що він похований у матеріалах, які не пов'язані з питанням (обтікання, перевірка помилок, модульне тестування).
Sepero

Виглядає добре, але хіба ви не забули кодер "промислової сили", який приймає ціле число плюс алфавіт для створення рядка?
martineau

1
Чи було q в останньому значенні навмисним, щоб показати ValueError, яке було піднято?
Thomas Vander Stichele

8

Якщо ви шукаєте найвищу ефективність (наприклад, django), вам потрібно щось на зразок наступного. Цей код є комбінацією ефективних методів від Baishampayan Ghose та WoLpH та 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

Можливо, ви також захочете розрахувати свій словник заздалегідь. (Примітка: Кодування за допомогою рядка показує більшу ефективність, ніж для списку, навіть при дуже довгих числах.)

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

Кодовано та декодовано 1 мільйон чисел менш ніж за 2,5 секунди. (2,2 ГГц i7-2670QM)


На початку не обов’язково потрібне tuple()оточення BASE_ALPH. У Python кожен рядок є ітерабельним. Звичайно, ця особливість використовується enumerate(). Тож код стає ще більш тонким :)
Луїс Нелл

7
Привіт, origiNell, ти маєш рацію, що кортеж () не потрібен, але в моїй системі це робить код запущеним приблизно на 20% швидше. Спробуйте протестувати його без кортежу () і подивіться, що вам найкраще підходить.
Вітаємо

1
Цікавий момент. Це має повний сенс, оскільки кортежі легші за струни. Дякую за просвітлення :)!
Луїс Нелл,

@Sepero Я ще більше вдосконалив вашу версію з точки зору форматування, іменування, тестів та функціональних можливостей (підтримуються негативні числа): pastebin.com/4uket7iu (ви можете оновити свою відповідь цим)
Джошуа

@Joschua - Ваш код за вашою URL-адресою для мене не працював. Здається, base_encode () генерував лише одну закодовану цифру для чисел, які я перевірив.
SMGreenfield

4

Якщо вам потрібно лише згенерувати короткий ідентифікатор (оскільки ви згадуєте скорочувачі URL-адрес), а не кодувати / декодувати щось, цей модуль може допомогти:

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


Я не впевнений, що це підходить для коротких URL-адрес. UUID, як правило, дуже велика кількість, тому навіть base57, що кодує його, як він, має бути довгим для короткої URL-адреси.
mikl

Ви можете просто вирізати скільки завгодно, зіткнення все ще будуть малоймовірними, оскільки це суто випадкові випадки, але більше не буде унікальним ідентифікатором.
Ставрос Корокітакіс,

4

Якщо ви використовуєте фреймворк django, ви можете використовувати модуль django.utils.baseconv.

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

На додаток до base62, baseconv також визначив base2 / base16 / base36 / base56 / base64.


3

Напевно, ви хочете base64, а не base62. Існує версія, сумісна з URL-адресами, яка плаває навколо, тому додаткові два символи заповнювача не повинні становити проблему.

Процес досить простий; враховуйте, що base64 представляє 6 бітів, а звичайний байт - 8. Призначте значення від 000000 до 111111 кожному з 64 обраних символів і складіть 4 значення разом, щоб відповідати набору з 3 байтів base256. Повторіть для кожного набору з 3 байтів, доповнивши кінцем пробіл, вибравши символ заповнення (0 зазвичай корисний).


5
Стандартні методи кодування Python base64 насправді не підходять для коротких URL-адрес, оскільки вони оптимізовані для кодування байтів (тобто рядків / букв) і дадуть більше результатів, ніж просто базове числове значення.
mikl,

@mikl Звичайно, модуль base64 Python може бути непридатним для генерації коротких URL-адрес, але всі методи кодування Python дійсно працюють над послідовностями чисел base-256. байти - це дійсно "рядки", закодовані базою 256. Python 2.x розглядає рядки як послідовність байтів, тоді як Python 3.x (що робить правильно) розглядає рядки як Unicode. Отже, b'foobar 'насправді є лише вигадливим способом написання [102, 111, 111, 98, 97, 114] або [0x66,0x6f, 0x6f, 0x62,0x61,0x72] або b' \ x66 \ x6f \ x6f \ x62 \ x61 \ x72 ', що, як не дивно, є поданням base-256. Байти не є рядками чи літерами. Байти - це байти. =)
глибоко

@yesudeep: Отже, байти - це байти ... і в чому саме ваша суть?
martineau

3

Зараз для цього існує бібліотека python.

Я працюю над створенням пакета pip для цього.

Я рекомендую вам використовувати мій bases.py https://github.com/kamijoutouma/bases.py, який надихнув 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

зверніться до https://github.com/kamijoutouma/bases.py#known-basesalphabets щодо того, які бази можна використовувати


2

Ви можете завантажити модуль zbase62 з pypi

напр

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

2
Так, я дивився на це раніше, але він перетворює рядки, а не числа :)
mikl

2

Я отримав велику користь від публікацій інших людей тут. Мені спочатку потрібен був код python для проекту Django, але з того часу я звернувся до node.js, тож ось версія JavaScript коду (частина кодування), яку надав 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"));

Я оновив цей код і зробив його проектом з відкритим кодом для всіх, хто цікавиться github.com/sbussard/encode-the-things
Стівен

2

Сподіваюсь, такий фрагмент може допомогти.

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

Використання для Вашого випадку:

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

Очевидно, що ви можете вказати інший алфавіт, що складається з меншої чи більшої кількості символів, тоді він перетворить ваше число на меншу або більшу цифрову базу. Наприклад, надання "01" як алфавіту виведе рядок, що представляє вхідний номер як двійковий.

Ви можете перетасувати алфавіт, щоб отримати своє унікальне представлення чисел. Це може бути корисно, якщо ви робите послугу скорочення URL.


1
Непогано. Ви можете використовувати if num < 0 or type(num) not in (int, long):.
martineau

Це вже краще, але це трохи складніше, тому longщо не існує в Py 3.x - тому, можливо, ви захочете скористатися цією відповіддю .
martineau

1
Або використовувати свій власний портативний варіант: isinstance(x, (type(1), type(2**32))).
martineau

2

Ось моє рішення:

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

пояснення

У будь-якій основі кожне число дорівнює a1+a2*base**2+a3*base**3...Отже, метою є знайти всеa s.

Для кожного N=1,2,3...коду aN*base**Nізолюється шляхом "модулювання", bдля b=base**(N+1)якого зрізи всі as більші за N, і зрізання всіх as, щоб їх послідовність була меншою, ніж Nзменшенням aкожного разу, коли функція викликається рекурсивно поточнимaN*base**N .

Base%(base-1)==1тому base**p%(base-1)==1і тому q*base^p%(base-1)==qлише за одним винятком, коли він q==base-1повертається 0. Щоб виправити цей випадок, він повертається 0. Функція перевіряє 0з самого початку.


переваги

У цьому зразку є лише одне множення (замість ділення) та деякі модульні операції, які все відносно швидко.


1

Особисто мені подобається рішення від Байшампаяна, головним чином через позбавлення заплутаних символів.

Для повноти та вирішення з кращою продуктивністю в цій публікації показано спосіб використання модуля Python base64.


1
Як згадувалося в моєму коментарі Вілліхаму Тотланду, Pythons base64 є неоптимальним для кодування чисел, оскільки він оптимізований для рядків.
mikl

1

Я писав це деякий час назад, і це працювало досить добре (негативи та все включено)

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

вибачте за довжину всього цього


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
Це виправляє назву BASE_LIST, а також змінює рядок декодування, який був пропущений у відмінній відповіді
Сперо

1

Ось рекурсивний та ітераційний спосіб зробити це. Ітераційний трохи швидший, залежно від кількості виконання.

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

Мені дуже сподобався ваш рекурсивний підхід. Моя дочка, яка приймала AP Comp Sci, придумала для мене те саме рішення для реалізації "base25" (використовуючи 'ABCDEFHJKMNPQRTUVWXY34789') в C ++. Я пішов перетворити його на Python, і, будучи абсолютно новим для цієї мови, вдарив кілька каменів спотикання - які ви елегантно вирішили в одному рядку коду! Ви навіть уникаєте поширеної проблеми з перекладом 0 на порожній рядок в алфавітах, які не починаються з 0-9. Чудова робота! (Мені не потрібні негативні числа, але ваш підхід був настільки хорошим, що, можливо, було б приємно додати, що для майбутніх браузерів)
SMGreenfield

1

Python 3.7.x

Я знайшов github доктора філософії для деяких алгоритмів при пошуку існуючого сценарію base62 . На даний момент це не спрацювало для поточної макс-версії Python 3, тому я пішов далі, виправив де потрібно і зробив невеликий рефакторинг. Я зазвичай не працюю з Python і завжди використовував його спеціально, тому YMMV. Вся заслуга доктора Чжихуа Лая . Я щойно розробив перегини для цієї версії Python.

файл 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

файл 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])}')

вихід try_base62.py

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

Оскільки в репо не було інформації про ліцензування, я подав PR, так що оригінальний автор принаймні знає, що інші люди використовують та модифікують їх код.


0

На жаль, я не можу допомогти вам з бібліотекою тут. Я вважаю за краще використовувати base64 і просто додавати додаткові символи за вашим вибором - якщо це можливо!

Тоді ви можете використовувати модуль base64.

Якщо це дійсно, насправді неможливо:

Ви можете зробити це самостійно таким чином (це псевдокод):

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

0

з простою рекурсією

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

Найпростіший.

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"))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.