어떤 기본의 정수를 문자열로 변환하는 방법?
파이썬은 주어진 기본 문자열에서 정수를 쉽게 만들 수 있습니다.
int(str, base).
나는 inverse : integer에서 문자열 생성 을 수행하고 싶습니다. 즉 int2base(num, base)
, 다음과 같은 함수를 원합니다 .
int(int2base(x, b), b) == x
함수 이름 / 인수 순서는 중요하지 않습니다.
어떤 번호 x
와 기본 받아 들일 것입니다.b
int()
이것은 작성하기 쉬운 함수입니다. 실제로이 질문에서 설명하는 것보다 쉽습니다. 그러나 뭔가 빠진 것 같아요.
나는 기능에 대해 알고 bin
, oct
, hex
,하지만 몇 가지 이유를 사용할 수 없습니다 :
이 함수는 이전 버전의 Python에서는 사용할 수 없으며 (2.2)와 호환되어야합니다.
다른 기지에 대해 같은 방식으로 호출 할 수있는 일반적인 솔루션을 원합니다.
2, 8, 16 이외의 기지를 허용하고 싶습니다
관련
- int (string, base)의 파이썬 우아한 역함수
- 파이썬에서 재귀를 사용하는 base-x 시스템의 정수
- 파이썬에서 기본 62 변환
- 파이썬에서 정수를 가장 짧은 URL 안전 문자열로 변환하는 방법은 무엇입니까?
고대 버전의 Python과의 호환성이 필요한 경우 gmpy 를 사용할 수 있습니다 (빠른 완전 일반 int-to-string 변환 함수를 포함하고 이러한 고대 버전 용으로 빌드 할 수 있음). 최신 버전은 유능한 Python 및 GMP 릴리스, 일부 최신 버전에 대해서만 테스트되지 않았거나 속도는 느리지 만 편리 성을 위해 Python 코드를 사용하십시오.
import string
digs = string.digits + string.ascii_letters
def int2base(x, base):
if x < 0:
sign = -1
elif x == 0:
return digs[0]
else:
sign = 1
x *= sign
digits = []
while x:
digits.append(digs[int(x % base)])
x = int(x / base)
if sign < 0:
digits.append('-')
digits.reverse()
return ''.join(digits)
놀랍게도 사람들은 작은 염기 (영어 알파벳 길이보다 작은)로 변환하는 솔루션 만 제공하고있었습니다. 2에서 무한대로 임의의 염기로 변환하는 해를 제공하려는 시도는 없었습니다.
다음은 매우 간단한 솔루션입니다.
def numberToBase(n, b):
if n == 0:
return [0]
digits = []
while n:
digits.append(int(n % b))
n //= b
return digits[::-1]
그래서 당신은베이스에 약간의 슈퍼 거대한 숫자로 변환해야하는 경우 577
,
numberToBase(67854 ** 15 - 102, 577)
올바른 솔루션을 제공합니다. [4, 473, 131, 96, 431, 285, 524, 486, 28, 23, 16, 82, 292, 538, 149, 25, 41, 483, 100, 517, 131, 28, 0, 435, 197, 264, 455]
,
나중에 원하는베이스로 변환 할 수있는
def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])
심판 : http://code.activestate.com/recipes/65212/
이로 인해
RuntimeError: maximum recursion depth exceeded in cmp
매우 큰 정수의 경우.
"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144
좋은 답변입니다! 내 질문에 대한 대답이 "아니오"인 것 같습니다. 확실한 해결책이 없었습니다. 다음은 답변에 표현 된 좋은 아이디어를 요약하는 데 사용할 기능입니다.
- 발신자가 제공 한 문자 매핑 허용 (base64 인코딩 허용)
- 음수 및 0 확인
- 복소수를 튜플의 문자열로 매핑
def int2base(x,b,alphabet='0123456789abcdefghijklmnopqrstuvwxyz'): 'convert an integer to its string representation in a given base' if b<2 or b>len(alphabet): if b==64: # assume base64 rather than raise error alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" else: raise AssertionError("int2base base out of range") if isinstance(x,complex): # return a tuple return ( int2base(x.real,b,alphabet) , int2base(x.imag,b,alphabet) ) if x<=0: if x==0: return alphabet[0] else: return '-' + int2base(-x,b,alphabet) # else x is non-negative real rets='' while x>0: x,idx = divmod(x,b) rets = alphabet[idx] + rets return rets
파이썬에는 임의의 기준으로 정수를 인쇄하는 내장 함수가 없습니다. 원한다면 직접 작성해야합니다.
baseconv.py
내 프로젝트에서 사용할 수 있습니다 : https://github.com/semente/python-baseconv
샘플 사용법 :
>>> from baseconv import BaseConverter
>>> base20 = BaseConverter('0123456789abcdefghij')
>>> base20.encode(1234)
'31e'
>>> base20.decode('31e')
'1234'
>>> base20.encode(-1234)
'-31e'
>>> base20.decode('-31e')
'-1234'
>>> base11 = BaseConverter('0123456789-', sign='$')
>>> base11.encode('$1234')
'$-22'
>>> base11.decode('$-22')
'$1234'
이 예를 들어 같은 일부 bultin 컨버터이다 baseconv.base2
, baseconv.base16
하고 baseconv.base64
.
재귀
나는 것이다 단순화 대부분의 투표 대답 에를 :
BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(n, b):
return "0" if not n else to_base(n//b, b).lstrip("0") + BS[n%b]
RuntimeError: maximum recursion depth exceeded in cmp
매우 큰 정수와 음수에 대해 동일한 조언을 제공 합니다. (당신은 사용할 수 있습니다 sys.setrecursionlimit(new_limit)
)
반복적 인
하려면 재귀 문제를 방지 :
BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(s, b):
res = ""
while s:
res+=BS[s%b]
s//= b
return res[::-1] or "0"
>>> numpy.base_repr(10, base=3) '101'
http://code.activestate.com/recipes/65212/
def base10toN(num,n):
"""Change a to a base-n number.
Up to base-36 is supported without special notation."""
num_rep={10:'a',
11:'b',
12:'c',
13:'d',
14:'e',
15:'f',
16:'g',
17:'h',
18:'i',
19:'j',
20:'k',
21:'l',
22:'m',
23:'n',
24:'o',
25:'p',
26:'q',
27:'r',
28:'s',
29:'t',
30:'u',
31:'v',
32:'w',
33:'x',
34:'y',
35:'z'}
new_num_string=''
current=num
while current!=0:
remainder=current%n
if 36>remainder>9:
remainder_string=num_rep[remainder]
elif remainder>=36:
remainder_string='('+str(remainder)+')'
else:
remainder_string=str(remainder)
new_num_string=remainder_string+new_num_string
current=current/n
return new_num_string
동일한 링크에서 다른 것이 있습니다
def baseconvert(n, base):
"""convert positive decimal integer n to equivalent in another base (2-36)"""
digits = "0123456789abcdefghijklmnopqrstuvwxyz"
try:
n = int(n)
base = int(base)
except:
return ""
if n < 0 or base < 2 or base > 36:
return ""
s = ""
while 1:
r = n % base
s = digits[r] + s
n = n / base
if n == 0:
break
return s
나는 이것을 위해 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 를 참조하십시오.
편집 : 핍 링크 https://pypi.python.org/pypi/bases.py/0.2.2
def base(decimal ,base) :
list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
other_base = ""
while decimal != 0 :
other_base = list[decimal % base] + other_base
decimal = decimal / base
if other_base == "":
other_base = "0"
return other_base
print base(31 ,16)
산출:
"1F"
>>> import string
>>> def int2base(integer, base):
if not integer: return '0'
sign = 1 if integer > 0 else -1
alphanum = string.digits + string.ascii_lowercase
nums = alphanum[:base]
res = ''
integer *= sign
while integer:
integer, mod = divmod(integer, base)
res += nums[mod]
return ('' if sign == 1 else '-') + res[::-1]
>>> int2base(-15645, 23)
'-16d5'
>>> int2base(213, 21)
'a3'
관심있는 사람들을위한 재귀 솔루션. 물론 음의 이진 값에는 작동하지 않습니다. Two 's Complement를 구현해야합니다.
def generateBase36Alphabet():
return ''.join([str(i) for i in range(10)]+[chr(i+65) for i in range(26)])
def generateAlphabet(base):
return generateBase36Alphabet()[:base]
def intToStr(n, base, alphabet):
def toStr(n, base, alphabet):
return alphabet[n] if n < base else toStr(n//base,base,alphabet) + alphabet[n%base]
return ('-' if n < 0 else '') + toStr(abs(n), base, alphabet)
print('{} -> {}'.format(-31, intToStr(-31, 16, generateAlphabet(16)))) # -31 -> -1F
def int2base(a, base, numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
baseit = lambda a=a, b=base: (not a) and numerals[0] or baseit(a-a%b,b*base)+numerals[a%b%(base-1) or (a%b) and (base-1)]
return baseit()
설명
어떤 기준에서든 모든 숫자는 a1+a2*base**2+a3*base**3...
"임무"와 같습니다 .
모든 N=1,2,3...
코드에서 슬라이스 aN*base**N
a는 b=base**(N+1)
모두 N보다 큰 b에 의해 "mouduling"을 분리하고 , func가 전류에 의해 호출 될 때마다 펑션이 감소 할 때마다 직렬 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을 반환하는 경우 수정하려면 func이 확인하는 것이 시작부터 0입니다.
장점
이 샘플에는 (분할 대신) 단 하나의 곱셈과 상대적으로 적은 시간이 걸리는 일부 모류가 있습니다.
num = input("number")
power = 0
num = int(num)
while num > 10:
num = num / 10
power += 1
print(str(round(num, 2)) + "^" + str(power))
def base_changer(number,base):
buff=97+abs(base-10)
dic={};buff2='';buff3=10
for i in range(97,buff+1):
dic[buff3]=chr(i)
buff3+=1
while(number>=base):
mod=int(number%base)
number=int(number//base)
if (mod) in dic.keys():
buff2+=dic[mod]
continue
buff2+=str(mod)
if (number) in dic.keys():
buff2+=dic[number]
else:
buff2+=str(number)
return buff2[::-1]
def dec_to_radix(input, to_radix=2, power=None):
if not isinstance(input, int):
raise TypeError('Not an integer!')
elif power is None:
power = 1
if input == 0:
return 0
else:
remainder = input % to_radix**power
digit = str(int(remainder/to_radix**(power-1)))
return int(str(dec_to_radix(input-remainder, to_radix, power+1)) + digit)
def radix_to_dec(input, from_radix):
if not isinstance(input, int):
raise TypeError('Not an integer!')
return sum(int(digit)*(from_radix**power) for power, digit in enumerate(str(input)[::-1]))
def radix_to_radix(input, from_radix=10, to_radix=2, power=None):
dec = radix_to_dec(input, from_radix)
return dec_to_radix(dec, to_radix, power)
또 다른 짧은 것 (그리고 이해하기 쉬운) :
def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
return (int_to_str(n/b, b, symbols) if n >= b else "") + symbols[n%b]
적절한 예외 처리 :
def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
try:
return (int_to_str(n/b, b) if n >= b else "") + symbols[n%b]
except IndexError:
raise ValueError(
"The symbols provided are not enough to represent this number in "
"this base")
베이스 2에서 10까지 작동하는 다른 솔루션은 더 높은베이스에 대한 수정이 필요합니다.
def n2b(n, b):
if n == 0:
return 0
d = []
while n:
d.append(int(n % b))
n /= b
return ''.join(map(str,d[::-1]))
예:
n2b(10,2) => '10100'
int(n2b(10,2),2) => 10
다음은 부호있는 정수 및 사용자 정의 숫자를 처리하는 재귀 버전입니다.
import string
def base_convert(x, base, digits=None):
"""Convert integer `x` from base 10 to base `base` using `digits` characters as digits.
If `digits` is omitted, it will use decimal digits + lowercase letters + uppercase letters.
"""
digits = digits or (string.digits + string.ascii_letters)
assert 2 <= base <= len(digits), "Unsupported base: {}".format(base)
if x == 0:
return digits[0]
sign = '-' if x < 0 else ''
x = abs(x)
first_digits = base_convert(x // base, base, digits).lstrip(digits[0])
return sign + first_digits + digits[x % base]
문자열은 숫자를 나타내는 유일한 선택은 아닙니다. 정수 목록을 사용하여 각 숫자의 순서를 나타낼 수 있습니다. 그것들은 쉽게 문자열로 변환 될 수 있습니다.
어떤 답도 base <2를 거부하지 않습니다. 대부분이 매우 느리게 실행하거나 스택에 대한 오버 플로우와 충돌합니다 매우 큰 수 (** 43210와 같은 56789). 이러한 실패를 피하려면 다음과 같이 빠르게 줄이십시오.
def n_to_base(n, b):
if b < 2: raise # invalid base
if abs(n) < b: return [n]
ret = [y for d in n_to_base(n, b*b) for y in divmod(d, b)]
return ret[1:] if ret[0] == 0 else ret # remove leading zeros
def base_to_n(v, b):
h = len(v) // 2
if h == 0: return v[0]
return base_to_n(v[:-h], b) * (b**h) + base_to_n(v[-h:], b)
assert ''.join(['0123456789'[x] for x in n_to_base(56789**43210,10)])==str(56789**43210)
Speedwise n_to_base
는 str
많은 수 (내 기계에서 약 0.3 초)와 비교할 수 있지만, 비교 hex
하면 내 기계에서 약 0.3ms 또는 1000 배 빠릅니다. 그 이유는 큰 정수가 기본 256 (바이트)의 메모리에 저장되기 때문입니다. 각 바이트는 단순히 2 문자 16 진 문자열로 변환 될 수 있습니다. 이 정렬은 2의 거듭 제곱 인 염기에 대해서만 발생하므로 2, 8 및 16 (및 base64, ascii, utf16, utf32)에 대한 특별한 경우가 있습니다.
십진 문자열의 마지막 숫자를 고려하십시오. 정수를 형성하는 바이트 시퀀스와 어떤 관련이 있습니까? 하자가 바이트 라벨 s[i]
과 함께 s[0]
최하위 (리틀 엔디안)되고 있습니다. 그런 다음 마지막 숫자는 sum([s[i]*(256**i) % 10 for i in range(n)])
입니다. 256 ** i는 i> 0 (6 * 6 = 36)에 대해 6으로 끝나므로 마지막 숫자는 (s[0]*5 + sum(s)*6)%10
입니다. 이것으로부터, 마지막 숫자는 모든 바이트의 합에 의존한다는 것을 알 수 있습니다. 이 비 로컬 속성은 10 진수로의 변환을 어렵게 만듭니다.
def baseConverter(x, b):
s = ""
d = string.printable.upper()
while x > 0:
s += d[x%b]
x = x / b
return s[::-1]
여기에 플로트 변환기가 없습니다. 그리고 나는 항상 세 자리로 그룹화를 놓쳤다.
할 것:
과학적인 표현에 - 민수기 (n.nnnnnn*10**(exp)
- (가) '10'
입니다self.baseDigits[1::-1]/self.to_string(len (self.baseDigits))
-from_string-function.
-base 1-> 로마 숫자?
agles와 복잡한 repr
그래서 여기 내 해결책이 있습니다 :
DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz"
# note that the order of the digits is reversed for digits before the point
NO_GROUPING = lambda g: g
concat = "".join
concat_backwards = lambda g: concat(e for e in reversed(list(g)))
def grouping(length = 3, char = '_'):
def yieldor(digits):
i = 0
for d in digits:
if i == length:
yield char
i = 0
yield d
i+=1
return yieldor
class Converter:
def __init__(self, baseDigits: (int, str), beforePoint = NO_GROUPING, afterPoint = NO_GROUPING, decimalPoint = '.', digitPrecision = 16, trimZeros = True):
if isinstance(baseDigits, int):
baseDigits = DIGITS[:baseDigits]
self.baseDigits = baseDigits
self.beforePoint = beforePoint
self.afterPoint = afterPoint
self.decimalPoint = decimalPoint
self.digitPrecision = digitPrecision
self.trimZeros = trimZeros
def to_string(self, number: (int, float, complex)) -> str:
if isinstance(number, complex):
if number.imag == 0:
return self.to_string(number.real)
if number.real == 0:
return self.to_string(number.imag) + 'j'
return "({}+{}j)".format(self.to_string(number.real), self.to_string (number.imag))
if number < 0:
return '-' + self.to_string(-number)
digitCount = len(self.baseDigits)
if isinstance(number, float):
# round correctly
precError=digitCount**-self.digitPrecision
number+=0.5*precError
if self.trimZeros:
def yieldor(n):
p = precError
for i in range(self.digitPrecision):
if n <= p:
return
p *= digitCount
n *= digitCount
digit = int(n)
n -= digit
yield self.baseDigits[digit]
else:
def yieldor(n):
for i in range(self.digitPrecision):
n *= digitCount
digit = int(n)
n -= digit
yield self.baseDigits[digit]
a = concat(self.afterPoint(yieldor(number%1)))
return (
self.to_string(int(number)) + (a and self.decimalPoint + a)
)
else: #is int
if not number: return self.baseDigits[0]
def yieldor(n):
while n:
n, digit = divmod(n, digitCount)
yield self.baseDigits[digit]
return concat_backwards(self.beforePoint(yieldor(number)))
# some tests:
if __name__ == "__main__":
def conv_test(num, digits, *argv, **kwv):
print(num, "->", digits if isinstance(digits, int) else "{} ({})".format(len(digits), digits), Converter(digits, *argv, **kwv).to_string(num))
conv_test(True, "ft")
conv_test(123, 12, grouping(2))
conv_test(-0xf00d, 16)
conv_test(1000, True<<True, grouping(4))
conv_test(1_000_000, "0+-", beforePoint = grouping(2, '|'))
conv_test(1.5, 10)
conv_test(0.999999999, 10, digitPrecision = 8)
conv_test(-0.1, 10)
import math
conv_test(math.pi, 10, afterPoint = grouping(5, ' '))
conv_test(0.123456789, 10, digitPrecision = 6)
grSpc = grouping(1, ' ')
conv_test(math.e, ["off", "on"], grSpc, grSpc, " dot ", digitPrecision = 7)
conv_test(1 + 1.5j, 10)
conv_test(50j, 10)
conv_test(10.01, '-<>')
# and generate some brainfuck-code here:
conv_test(1701**42, '+-<>,.][', digitPrecision = 32)
def bn(x,b,ab="0123456789abcdefghijklmnopqrstuvwxyz..."
a = ""
while (x>0):
x,r = divmod(x,n)
a += ab[r]
return a[::-1]
bn(2**100, 36)
산출:
3ewfdnca0n6ld1ggvfgg
어떤 기본으로 변환하기 위해, 역도 쉽습니다.
참고 URL : https://stackoverflow.com/questions/2267362/how-to-convert-an-integer-in-any-base-to-a-string
'Programing' 카테고리의 다른 글
Lodash는 배열에서 중복 제거 (0) | 2020.05.16 |
---|---|
값으로 배열 인덱스를 찾는 방법은 무엇입니까? (0) | 2020.05.16 |
linq 결과를 HashSet 또는 HashedSet로 변환하는 방법 (0) | 2020.05.16 |
사람들은 왜 루비가 느리다고 말합니까? (0) | 2020.05.16 |
PHP로 문자열의 처음 4자를 제거 (0) | 2020.05.16 |