정수를 기본 62로 변환하는 방법 (16 진수와 같지만 다음 숫자 : '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').
나는 그것을 위해 좋은 파이썬 라이브러리를 찾으려고 노력해 왔지만 모두 문자열 변환으로 가득 찬 것처럼 보입니다. Python base64 모듈은 문자열 만 받아들이고 한 자리를 4 자로 바꿉니다. URL 단축기가 사용하는 것과 유사한 것을 찾고있었습니다.
정수를 기본 62로 변환하는 방법 (16 진수와 같지만 다음 숫자 : '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').
나는 그것을 위해 좋은 파이썬 라이브러리를 찾으려고 노력해 왔지만 모두 문자열 변환으로 가득 찬 것처럼 보입니다. Python base64 모듈은 문자열 만 받아들이고 한 자리를 4 자로 바꿉니다. URL 단축기가 사용하는 것과 유사한 것을 찾고있었습니다.
답변:
이에 대한 표준 모듈은 없지만이를 달성하기 위해 자체 함수를 작성했습니다.
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"
즐기세요.
$-_.+!*'(),;/?:@&= 당신은 아마 너무 같은 다른 문자를 사용할 수 있습니다 []~등
한 번도이 작업을 수행하는 스크립트를 작성했는데 꽤 우아하다고 생각합니다. :)
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)
reversed(string)슬라이싱보다 더 빠르게 사용 하는 경우 string[::-1].
integer /= length해야 integer //=length했습니다
다음 디코더 제작자는 합리적인 기준으로 작업하고 훨씬 깔끔한 루프를 가지고 있으며 잘못된 문자를 만나면 명시적인 오류 메시지를 제공합니다.
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)
**루프에서 오퍼레이터로 반전하는 미키 마우스가 없습니다 .
가장 높은 효율성 (예 : 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(). 코드 :도 날씬 얻을 수 있도록
무언가를 인코딩 / 디코딩하는 대신 짧은 ID (URL 단축기를 언급했기 때문에)를 생성하기 만하면이 모듈이 도움이 될 수 있습니다.
아마도 base62가 아닌 base64를 원할 것입니다. URL 호환 버전이 떠 다니므로 추가로 두 개의 필러 문자가 문제가되지 않습니다.
과정은 매우 간단합니다. base64는 6 비트를 나타내고 일반 바이트는 8을 나타냅니다. 선택한 64 자 각각에 000000에서 111111 사이의 값을 할당하고 3 개의 base256 바이트 세트와 일치하도록 4 개의 값을 합칩니다. 3 바이트의 각 세트에 대해 반복하고 마지막에 선택한 패딩 문자로 패딩합니다 (일반적으로 0이 유용함).
이제이를위한 파이썬 라이브러리가 있습니다.
나는 이것을 위해 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 를 참조 하세요.
나는 여기에 다른 사람들의 게시물을 통해 큰 혜택을 얻었습니다. 원래 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"));
다음 스 니펫이 도움이되기를 바랍니다.
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 단축 서비스를 만드는 경우 도움이 될 수 있습니다.
if num < 0 or type(num) not in (int, long):.
longPy 3.x에는 존재하지 않기 때문에 조금 더 복잡 하므로이 답변 을 사용하고 싶을 수도 있습니다 .
isinstance(x, (type(1), type(2**32))).
내 해결책은 다음과 같습니다.
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은 처음부터 확인합니다 .
이 샘플에는 하나의 곱셈 (나눗셈 대신)과 일부 모듈러스 연산이 있으며 모두 상대적으로 빠릅니다.
나는 이것을 얼마 전에 썼고 꽤 잘 작동했습니다 (음수 및 모두 포함)
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
모든 길이에 대해 죄송합니다
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
이를 수행하는 반복적이고 반복적 인 방법이 있습니다. 반복적 인 것은 실행 횟수에 따라 조금 더 빠릅니다.
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
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.pyimport 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을 제출 했으므로 원래 작성자는 최소한 다른 사람들이 자신의 코드를 사용하고 수정하고 있음을 알고 있습니다.
간단한 재귀로
"""
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)
가장 간단합니다.
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"))