기본 62 변환


92

정수를 기본 62로 변환하는 방법 (16 진수와 같지만 다음 숫자 : '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').

나는 그것을 위해 좋은 파이썬 라이브러리를 찾으려고 노력해 왔지만 모두 문자열 변환으로 가득 찬 것처럼 보입니다. Python base64 모듈은 문자열 만 받아들이고 한 자리를 4 자로 바꿉니다. URL 단축기가 사용하는 것과 유사한 것을 찾고있었습니다.


누군가 같은 소리는 오픈 소스 프로젝트의 아이디어는 : 당신은 아무것도를 찾거나 직접 만들하기로 결정 알려줘 발견 ...
samoz

짧은 URL을 만들려면 인코딩 할 필요가없는 전체 문자 집합을 사용하는 것이 좋습니다. en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters . 66 자입니다.
l0b0

사용자의 혼동을 피하기 위해 점과 물결표를 전달할 것이라고 생각하지만 대시와 밑줄은 가치있는 추가가되어야합니다. 감사합니다.
mikl

Base64는 어떻습니까? 이를 위해 라이브러리를 찾는 것이 더 좋을 것입니다.
Mike Cooper

이 질문에는 적용 가능한 여러 답변이 있습니다. stackoverflow.com/questions/561486/…
Miles

답변:


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 기지에서 /로 디코딩 / 인코딩.

도움이 되었기를 바랍니다.

추신-URL 단축기의 경우 0Ol1oI 등과 같은 몇 가지 혼란스러운 문자를 생략하는 것이 더 낫다는 것을 알았습니다. 따라서 URL 단축 요구에이 알파벳을 사용합니다. "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

즐기세요.


5
+1 : 좋아요! 더 많은 URL 친화적 인 문자로 확장하여 한 문자를 여기저기서 저장할 수 있습니다. 나는 안전 알고 문자는 다음과 같습니다 $-_.+!*'(),;/?:@&= 당신은 아마 너무 같은 다른 문자를 사용할 수 있습니다 []~
Blixt

24
이름 지정 버그 : 알파벳을 사용자 정의 할 수 있으므로 기본 62가 아닙니다.
언 와인드

3
디코드의 경우 전력을 계산하지 않는 것이 좋습니다 (시간을 절약하고 쓰기 시간이 더 짧지 만 더 중요한 것은 하나씩 오류를 방지 함). num = 0; 문자열의 문자 : num = num * base + alphabet.index (char)
ShreevatsaR

1
@ShreevatsaR : 사전 조회 대신 str.index ()를 사용하는 특별한 이유가 있습니까? 내 대답을 참조하십시오 ...
John Machin

2
Jonathan-Python은 임의 길이의 수를 처리 할 수 ​​있습니다. 오버플로가 없습니다. >>> 256 * (62 ** 100) 44402652562862911414971048359760030835982580330786570771137804709455598239929932673552190201125730101070867075377228748911717860448985185350731601887476350502973424822800696272224256L
Anthony Briggs

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
이 버전은 Baishampayan에서 허용하는 솔루션보다 훨씬 빠릅니다. 함수 외부의 길이를 계산하여 더 최적화했습니다. 테스트 결과 (100,000 회 반복) : version-WoLpH : .403 .399 .399 .398 .398 | 버전 -Baishampayan : 1.783 1.785 1.782 1.788 1.784. 이 버전은 약 4 배 빠릅니다.
요르단

base_decode 함수에서 reversed(string)슬라이싱보다 더 빠르게 사용 하는 경우 string[::-1].
ENDOH takanao 2014 년

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 2013 년

@Sepero : 뭐가 그렇게 재밌 니? 강력하고 강력한 산업 소프트웨어입니다. **루프에서 오퍼레이터로 반전하는 미키 마우스가 없습니다 .
John Machin

친구를 진정 시키십시오. 네가 옳아. 질문 (래핑, 오류 검사, 단위 테스트)과 관련이없는 항목에 묻혀 있기 때문에 내부 루프의 진정한 장점을 놓쳤습니다.
Sepero

괜찮아 보이지만 문자열을 생성하기 위해 정수와 알파벳을 사용하는 "산업용"인코더를 잊으 셨나요?
martineau 2013-01-17

1
마지막 값의 q가 ValueError가 발생했음을 보여주기위한 것입니까?
Thomas Vander Stichele 2014 년

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

2.5 초 이내에 백만 개의 숫자를 인코딩 및 디코딩했습니다. (2.2Ghz i7-2670QM)


처음 에는 tuple()주변 BASE_ALPH이 필요하지 않습니다 . 파이썬에서 모든 문자열은 반복 가능합니다. 이 기능은 물론 enumerate(). 코드 :도 날씬 얻을 수 있도록
루이스 이모에게

7
안녕하세요 origiNell, tuple ()이 필요하지 않다는 말이 맞지만 제 시스템에서는 코드가 약 20 % 더 빠르게 실행됩니다. tuple ()없이 테스트 해보고 무엇이 가장 적합한 지 확인하십시오. 건배 :)
Sepero

1
흥미로운 점. 튜플이 문자열보다 가볍기 때문에 총체적으로 의미가 있습니다. 깨달음을 주셔서 감사합니다 :)!
Luis Nell 2013

내가 더 (음수가 지원), 테스트 및 기능을 명명, 포맷의 측면에서 버전을 개선 @Sepero : pastebin.com/4uket7iu을 (당신이 가진 당신의 대답을 업데이트 할 수 있습니다)
Joschua

@Joschua-URL의 코드가 작동하지 않았습니다. base_encode ()는 내가 테스트 한 숫자에 대해 하나의 인코딩 된 숫자 만 생성하는 것처럼 보였습니다.
SMGreenfield

4

무언가를 인코딩 / 디코딩하는 대신 짧은 ID (URL 단축기를 언급했기 때문에)를 생성하기 만하면이 모듈이 도움이 될 수 있습니다.

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


짧은 URL에 적합한 지 잘 모르겠습니다. UUID는 일반적으로 매우 큰 숫자이므로 그가하는 것처럼 base57 인코딩도 짧은 URL에 대해 다소 길어질 수 있습니다.
mikl

원하는만큼 잘라낼 수 있습니다. 순전히 무작위이기 때문에 충돌이 발생할 가능성은 낮지 만 더 이상 고유 ID가 아닙니다.
Stavros Korokithakis 2011 년

4

django 프레임 워크를 사용하는 경우 django.utils.baseconv 모듈을 사용할 수 있습니다.

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

base62 외에도 baseconv는 base2 / base16 / base36 / base56 / base64도 정의했습니다.


3

아마도 base62가 아닌 base64를 원할 것입니다. URL 호환 버전이 떠 다니므로 추가로 두 개의 필러 문자가 문제가되지 않습니다.

과정은 매우 간단합니다. base64는 6 비트를 나타내고 일반 바이트는 8을 나타냅니다. 선택한 64 자 각각에 000000에서 111111 사이의 값을 할당하고 3 개의 base256 바이트 세트와 일치하도록 4 개의 값을 합칩니다. 3 바이트의 각 세트에 대해 반복하고 마지막에 선택한 패딩 문자로 패딩합니다 (일반적으로 0이 유용함).


5
표준 Python base64 인코딩 방법은 바이트 (예 : 문자열 / 문자) 인코딩에 최적화되어 있기 때문에 짧은 URL에 실제로 적합하지 않으며 숫자 값을 기본 이동하는 것보다 더 긴 출력을 생성합니다.
mikl 2010-04-02

@mikl 물론, Python의 base64 모듈은 짧은 URL을 생성하는 데 적합하지 않을 수 있지만 모든 Python의 인코딩 방법은 실제로 base-256 숫자 시퀀스에서 작동합니다. 바이트는 실제로 기본 256으로 인코딩 된 "문자열"입니다. Python 2.x는 문자열을 바이트 시퀀스로 취급하는 반면 Python 3.x (올바른 일을 수행)는 문자열을 유니 코드로 취급합니다. 따라서 b'foobar '는 [102, 111, 111, 98, 97, 114] 또는 [0x66,0x6f, 0x6f, 0x62,0x61,0x72] 또는 b'\ x66 \ x6f \ x6f \를 쓰는 멋진 방법 일뿐입니다. x62 \ x61 \ x72 '는 당연히 base-256 표현입니다. 바이트는 문자열이나 문자가 아닙니다. 바이트는 바이트입니다. =)
yesudeep 2011 년

@yesudeep : 그래서, 바이트는 바이트입니다… 그리고 정확히 당신의 요점은 무엇입니까?
martineau 2013-01-17

3

이제이를위한 파이썬 라이브러리가 있습니다.

나는 이것을 위해 pip 패키지를 만드는 중입니다.

bases.js 에서 영감을 얻은 bases.py https://github.com/kamijoutouma/bases.py 를 사용하는 것이 좋습니다.

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

pypi 에서 zbase62 모듈을 다운로드 할 수 있습니다.

예 :

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

2
그래, 그 이전에보고하지만 :) 문자열이 아닌 숫자로 변환
mikl

2

나는 여기에 다른 사람들의 게시물을 통해 큰 혜택을 얻었습니다. 원래 Django 프로젝트를 위해 파이썬 코드가 필요했지만 그 이후로 node.js로 전환했습니다. 그래서 여기 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
Stephen

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 2013-06-25

더 낫지 만 longPy 3.x에는 존재하지 않기 때문에 조금 더 복잡 하므로이 답변 을 사용하고 싶을 수도 있습니다 .
martineau 2013-06-25

1
또는 나만의 휴대용 버전을 사용하십시오 : isinstance(x, (type(1), type(2**32))).
martineau 2013-06-25

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하여 "moduloing"에 의해 b를 위해 b=base**(N+1)하는 모든 조각 a보다 더이야 N, 모든이 슬라이스 a자신의 시리얼보다 작은 너무 s의 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

개인적으로 저는 Baishampayan의 솔루션을 좋아하는데, 대부분 혼란스러운 문자를 제거했기 때문입니다.

완전성과 더 나은 성능을위한 솔루션을 위해이 게시물 은 Python base64 모듈을 사용하는 방법을 보여줍니다.


1
Williham Totland에 대한 내 의견에서 언급했듯이 Pythons base64는 문자열에 최적화되어 있기 때문에 숫자 인코딩에 차선책입니다.
mikl 2010

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의 이름을 수정하고 또한 Spero의 우수한 답변에서 생략 된 디코딩 문자열을 뒤집습니다
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를 수강하던 제 딸은 C ++로 "base25"( 'ABCDEFHJKMNPQRTUVWXY34789'사용)를 구현할 수있는 동일한 솔루션을 찾았습니다. 나는 그것을 파이썬으로 변환하기 위해 가서 그 언어로 완전히 새로운 사람이 된 몇 가지 걸림돌이되었습니다 .-- 한 줄의 코드로 우아하게 해결했습니다! 0-9로 시작하지 않는 알파벳의 빈 문자열로 0이 번역되는 일반적인 문제도 피할 수 있습니다. 훌륭한 일! (I 음수가 필요하지 않습니다,하지만 좋은이 미래의 브라우저에 추가 할 수 있습니다 좋은 귀하의 접근 방식이었다)
SMGreenfield

1

파이썬 3.7.x

기존 base62 스크립트를 찾을 때 일부 알고리즘에 대한 PhD의 github를 찾았습니다 . 현재 Python 3의 현재 최대 버전에서는 작동하지 않았으므로 필요한 부분을 수정하고 약간의 리팩토링을 수행했습니다. 저는 보통 Python으로 작업하지 않으며 항상 YMMV처럼 임시로 사용했습니다. 모든 신용은 Dr. Zhihua Lai에게 있습니다. 방금이 버전의 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"))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.