Преобразование по базе 62


92

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

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


Похоже, кто-то только что нашел идею проекта с открытым исходным кодом :) Дайте мне знать, если вы что-нибудь найдете или решите создать свой собственный ...
samoz

Если вы хотите создать короткие URL-адреса, вы можете использовать весь набор символов, которые не нужно кодировать: en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters . Это 66 символов.
l0b0

Думаю, я пропущу точку и тильду, чтобы избежать путаницы у пользователей, но тире и подчеркивания должны быть полезными дополнениями, спасибо.
Mikl

что насчет Base64? Возможно, вам больше повезет найти для этого библиотеки.
Майк Купер,

На этот вопрос есть несколько подходящих ответов: 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, чтобы можно было сохранить по одному символу здесь и там. Персонажи, которые, как я знаю, безопасны: $-_.+!*'(),;/?:@&= вы, вероятно, можете использовать и другие персонажи, например, []~и т. Д.
Бликст,

24
Ошибка наименования: это не база 62, так как алфавит настраивается.
расслабьтесь

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

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 итераций): версия-WoLpH: .403 .399 .399 .398 .398 | версия-Байшампаян: 1,783 1,785 1,782 1,788 1,784. Эта версия примерно в 4 раза быстрее.
Jordan

если использовать reversed(string)быстрее, чем нарезка string[::-1]в функции base_decode.
ENDOH takanao

1
Мне потребовалось много времени, чтобы найти этот вопрос. Никогда не знал, что это называется преобразованием base62. Хороший ответ.

1
Мне пришлось изменить integer /= lengthна, integer //=lengthчтобы получить правильный остаток
Карлголд

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: Что в этом смешного? Это серьезное, надежное программное обеспечение промышленного уровня. Никакого реверсирования Микки-Мауса с **оператором в цикле.
Джон Мачин

Успокойся, друг. Ты прав. Я упустил истинное совершенство вашего внутреннего цикла из-за того, что он был похоронен внутри вещей, не связанных с вопросом (упаковка, проверка ошибок, модульное тестирование).
Sepero

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

1
Было ли q в последнем значении намеренно, чтобы показать, что возникает ошибка ValueError?
Thomas Vander Stichele

8

Если вы ищете максимальную эффективность (например, django), вам понадобится что-то вроде следующего. Этот код представляет собой комбинацию эффективных методов от Байшампаяна Гхоша, WoLpH и Джона Мачина.

# 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, вы правы, что tuple () не нужен, но в моей системе он заставляет код работать примерно на 20% быстрее. Попробуйте протестировать его без tuple () и посмотрите, что лучше всего подходит для вас. Cheers :)
Sepero

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 02

@mikl Конечно, модуль Python base64 может не подходить для создания коротких URL-адресов, но все методы кодирования Python действительно работают с числовыми последовательностями base-256. байты - это действительно "строки" в кодировке base-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 09

@yesudeep: Итак, байты - это байты ... и что именно вы хотите сказать?
Мартино

3

Для этого теперь есть библиотека Python.

Я работаю над созданием пакета pip для этого.

Я рекомендую вам использовать мой base.py https://github.com/kamijoutouma/bases.py, который был вдохновлен base.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

Мне очень помогли публикации здесь других людей. Первоначально мне был нужен код Python для проекта Django, но с тех пор я обратился к node.js, поэтому вот версия кода javascript (часть кодирования), которую предоставил Байшампаян Гхош.

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):.
Мартино

Это лучше, но немного сложнее, потому что longего нет в Py 3.x, поэтому можно использовать этот ответ .
Мартино

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...Итак, цель состоит в том, чтобы найти все as.

Для каждого N=1,2,3...код изолирует " aN*base**Nпо модулю" наb для b=base**(N+1)которого все срезы aбольше чем N, и нарезая все срезы aтак, чтобы их серийный номер был меньше, чем 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
Как упоминалось в моем комментарии к Williham Totland, Pythons base64 не оптимален для кодирования чисел, поскольку он оптимизирован для строк.
mikl 02

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, а также меняет строку при декодировании, которая была опущена в отличном во всем остальном ответе Сперо
paulkav1

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 . На данный момент это не сработало для текущей max-версии 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.