102

您如何将整数转换为基数 62(如十六进制,但使用这些数字:'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')。

我一直在尝试为它找到一个好的 Python 库,但它们似乎都忙于转换字符串。Python base64 模块仅接受字符串并将单个数字转换为四个字符。我正在寻找类似于 URL 缩短器使用的东西。

4

22 回答 22

184

对此没有标准模块,但我已经编写了自己的函数来实现这一点。

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"

玩得开心。

于 2009-07-13T14:27:01.833 回答
59

我曾经也写过一个脚本来做这个,我认为它很优雅:)

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)
于 2010-03-30T23:58:33.093 回答
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)
于 2009-09-28T14:20:24.803 回答
9

如果您正在寻找最高效率(如 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

在 2.5 秒内编码和解码 100 万个数字。(2.2Ghz i7-2670QM)

于 2013-01-10T13:33:19.640 回答
5

如果你使用 django 框架,你可以使用 django.utils.baseconv 模块。

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

除了base62,baseconv还定义了base2/base16/base36/base56/base64。

于 2018-01-18T07:32:09.660 回答
4

如果您只需要生成一个短 ID(因为您提到了 URL 缩短器)而不是编码/解码某些东西,那么这个模块可能会有所帮助:

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

于 2011-01-08T14:59:07.033 回答
3

您可能需要 base64,而不是 base62。它有一个与 URL 兼容的版本,因此额外的两个填充字符应该不是问题。

这个过程相当简单;考虑 base64 代表 6 位,一个常规字节代表 8。为所选的 64 个字符中的每一个分配一个从 000000 到 111111 的值,并将 4 个值放在一起以匹配一组 3 个 base256 字节。对每组 3 个字节重复此操作,并在末尾使用您选择的填充字符进行填充(0 通常很有用)。

于 2009-07-13T14:26:05.423 回答
3

现在有一个python库。

我正在为此制作一个 pip 包。

我建议你使用我的 bases.py https://github.com/kamijotouma/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/kamijotouma/bases.py#known-basesalphabets 了解可用的碱基

于 2015-05-27T10:12:10.890 回答
2

你可以从pypi下载 zbase62 模块

例如

>>> import zbase62
>>> zbase62.b2a("abcd")
'1mZPsa'
于 2009-07-13T15:00:35.600 回答
2

我从其他人的帖子中受益匪浅。我最初需要用于 Django 项目的 python 代码,但从那以后我转向 node.js,所以这是 Baishampyan Ghose 提供的代码(编码部分)的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"));
于 2011-01-18T19:58:32.680 回答
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 缩短服务,它会很有帮助。

于 2013-06-05T16:54:30.797 回答
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)所有as 大于 s 的N切片,并切片所有as 以使它们的序列小于每次递归调用 current 函数N时减小。aaN*base**N

Base%(base-1)==1因此base**p%(base-1)==1,因此q*base^p%(base-1)==q只有一个例外,当q==base-1它返回时0。为了解决这种情况,它返回0. 该函数0从头开始检查。


好处

在这个示例中,只有一个乘法(而不是除法)和一些模运算,它们都相对较快。

于 2016-04-26T21:07:57.683 回答
1

我个人喜欢 Baishampayan 的解决方案,主要是因为剥离了令人困惑的字符。

为了完整性和性能更好的解决方案,这篇文章展示了一种使用 Python base64 模块的方法。

于 2009-07-14T03:55:44.687 回答
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

对这一切的长度感到抱歉

于 2011-02-28T00:36:23.750 回答
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
于 2013-03-29T00:50:19.217 回答
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
于 2014-10-15T15:13:04.937 回答
1

Python3.7.x

在寻找现有的 base62 脚本时,我找到了一些算法的博士 github 。目前它不适用于 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

由于 repo 中没有许可信息,我确实提交了PR,所以原作者至少知道其他人正在使用和修改他们的代码。

于 2019-09-26T05:19:34.210 回答
0

抱歉,这里的图书馆我不能帮你。我更喜欢使用 base64 并在您的选择中添加额外的字符——如果可能的话!

然后就可以使用 base64 模块了。

如果这真的,真的不可能:

你可以这样自己做(这是伪代码):

base62vals = []
myBase = 62
while num > 0:
   reminder = num % myBase
   num = num / myBase
   base62vals.insert(0, reminder)
于 2009-07-13T14:26:58.353 回答
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)

于 2019-07-17T05:42:54.570 回答
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"))
于 2020-05-06T22:48:13.160 回答
0

适用于 Python3(机器:i7-8565U)的基准测试答案:

"""
us per enc()+dec()  #  test

(4.477935791015625, 2, '3Tx16Db2JPSS4ZdQ4dp6oW')
(6.073190927505493, 5, '3Tx16Db2JPSS4ZdQ4dp6oW')
(9.051250696182251, 9, '3Tx16Db2JPSS4ZdQ4dp6oW')
(9.864609956741333, 6, '3Tx16Db2JOOqeo6GCGscmW')
(10.868197917938232, 1, '3Tx16Db2JPSS4ZdQ4dp6oW')
(11.018349647521973, 10, '3Tx16Db2JPSS4ZdQ4dp6oW')
(12.448230504989624, 4, '03Tx16Db2JPSS4ZdQ4dp6oW')
(13.016672611236572, 7, '3Tx16Db2JPSS4ZdQ4dp6oW')
(13.212724447250366, 8, '3Tx16Db2JPSS4ZdQ4dp6oW')
(24.119479656219482, 3, '3tX16dB2jpss4zDq4DP6Ow')
"""

from time import time

half = 2 ** 127
results = []


def bench(n, enc, dec):
    start = time()
    for i in range(half, half + 1_000_000):
        dec(enc(i))
    end = time()
    results.append(tuple([end - start, n, enc(half + 1234134134134314)]))


BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"


def encode(num, alphabet=BASE62):
    """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


bench(1, encode, decode)
###########################################################################################################
# Remove the `_@` below for base62, now it has 64 characters
BASE_ALPH = tuple(BASE62)
BASE_LIST = BASE62
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_ALPH))

###########################################################################################################
BASE_LEN = len(BASE_ALPH)


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


def 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


bench(2, encode, decode)

###########################################################################################################
from django.utils import baseconv

bench(3, baseconv.base62.encode, baseconv.base62.decode)


###########################################################################################################
def encode(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()


bench(4, encode, decode)


###########################################################################################################
def encode(num, sym=BASE62, join_symbol=''):
    if num == 0:
        return sym[0]

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


bench(5, encode, decode)

###########################################################################################################
from math import floor

base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
b = 62;


def decode(b62: str) -> int:
    limit = len(b62)
    res = 0
    for i in range(limit):
        res = b * res + base.find(b62[i])
    return res


def encode(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


bench(6, encode, decode)


###########################################################################################################
def encode(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    return s[dec] if dec < 62 else encode(dec // 62) + s[int(dec % 62)]


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


bench(7, encode, decode)


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


def decode(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = 0
    for i in range(len(b62) - 1, -1, -1):
        ret = ret + s.index(b62[i]) * (62 ** (len(b62) - i - 1))
    return ret


bench(8, encode, decode)


###########################################################################################################

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


def decode(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


bench(9, encode, decode)


###########################################################################################################

def encode(number: int, alphabet=BASE62, padding: int = 22) -> str:
    l = len(alphabet)
    res = []
    while number > 0:
        number, rem = divmod(number, l)
        res.append(alphabet[rem])
        if number == 0:
            break
    return "".join(res)[::-1]  # .rjust(padding, "0")


def decode(digits: str, lookup=BASE_DICT) -> int:
    res = 0
    last = len(digits) - 1
    base = len(lookup)
    for i, d in enumerate(digits):
        res += lookup[d] * pow(base, last - i)
    return res


bench(10, encode, decode)

###########################################################################################################

for row in sorted(results):
    print(row)
于 2021-02-27T20:35:27.473 回答
0

原始的javascript版本:

var hash = "", alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", alphabetLength = 
alphabet.length;
do {
  hash = alphabet[input % alphabetLength] + hash;
  input = parseInt(input / alphabetLength, 10);
} while (input);

来源:https ://hashids.org/

Python:

def to_base62(number):
  alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  alphabetLength = len(alphabet)
  result = ""
  while True:
    result = alphabet[number % alphabetLength] + result
    number = int(number / alphabetLength)
    if number == 0:
      break
  return result

print to_base62(59*(62**2) + 60*(62) + 61)
# result: XYZ
于 2021-06-03T22:06:44.977 回答