Python允许通过
从给定基础的字符串中轻松创建整数int(str, base).
我想执行反向:从整数创建字符串,
即我想要一些函数int2base(num, base)
,这样:
int(int2base(x, b), b) == x
函数名称/参数顺序并不重要。
对于x
将接受的任何数字b
和基数int()
。
这是一个很容易编写的函数:实际上它比在这个问题中描述它更容易。但是,我觉得我必须遗漏一些东西。
我了解函数bin
,oct
,hex
,但由于以下几个原因我无法使用它们:
旧版本的Python不提供这些功能,我需要兼容(2.2)
我想要一个可以用不同基础调用相同方式的通用解决方案
我想允许2,8,16
答案 0 :(得分:87)
def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])
REF: http://code.activestate.com/recipes/65212/
请注意,这可能会导致
RuntimeError: maximum recursion depth exceeded in cmp
非常大的整数。
答案 1 :(得分:85)
令人惊讶的是,人们只提供转换为小基数的解决方案(小于英文字母的长度)。没有尝试提供从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]
,
您可以稍后转换为您想要的任何基地
答案 2 :(得分:84)
如果你需要兼容古老版本的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)
答案 3 :(得分:69)
"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144
答案 4 :(得分:20)
很棒的答案! 我想我的问题的答案是“不”我没有错过一些明显的解决方案。 这是我将使用的功能,它浓缩了答案中表达的好主意。
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
答案 5 :(得分:14)
Python没有用于在任意基础中打印整数的内置函数。如果你愿意,你必须自己编写。
答案 6 :(得分:13)
您可以使用我的项目中的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
。
答案 7 :(得分:6)
我会简化将most voted answer简化为:
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"
答案 8 :(得分:4)
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
答案 9 :(得分:4)
我为此制作了一个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 什么基地可用
答案 10 :(得分:3)
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”
答案 11 :(得分:3)
>>> numpy.base_repr(10, base=3)
'101'
答案 12 :(得分:1)
感兴趣的人的递归解决方案。当然,这不适用于负二进制值。你需要实现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
答案 13 :(得分:1)
>>> 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'
答案 14 :(得分:1)
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...
&#34;任务&#34;是找到所有的。
对于每个N=1,2,3...
,代码都会将aN*base**N
与#34; mouduling&#34;隔离开来。用b表示b=base**(N+1)
,它将所有a大于N的切片,并通过每当func被当前{调用'时减少a来切断其序列小于N的所有a' {1}}。
基数%(基数-1)== 1因此基数** p%(基数-1)== 1因此q * base ^ p%(base-1)== q当q =时只有一个例外base-1返回0。 为了解决这个问题,如果它返回0,则func检查是否从初始化为0。
在这个样本中只有一次乘法(而不是除法)和一些相对需要少量时间的moudulueses。
答案 15 :(得分:1)
async ActiveNotif() {
this.ng.run(() => {
// reloading
var time = setInterval(callingFunction , 10000);
function callingFunction(){
this.http.get('flight=' + this.id + '', {}, {})
.then(data => {
let FlightDetails = JSON.parse(data.data);
this.identification = FlightDetails.identification.callsign;
this.Fstatus = FlightDetails.status.generic.status.text;
console.log(this.Fstatus)
});
if (this.Fstatus == "landed") {
this.localNotifications.schedule(
[
{
id:0,
title: 'Your flight has arrived',
text: 'Your flight ' + this.identification + 'is arrived',
trigger: { count: 1 },
sound: "file://assets/one.mp3"
},
]);
}
if (this.Fstatus == "landed") {
clearInterval(time)
}
}
})
}
答案 16 :(得分:1)
num = input("number")
power = 0
num = int(num)
while num > 10:
num = num / 10
power += 1
print(str(round(num, 2)) + "^" + str(power))
答案 17 :(得分:0)
假设我们要将 14 转换为基数 2。我们重复应用除法算法,直到商为 0:
14 = 2 x 7
7 = 2 x 3 + 1
3 = 2 x 1 + 1
1 = 2 x 0 + 1
二进制表示只是从下到上读取的余数。这可以通过展开来证明
14 = 2 x 7 = 2 x (2 x 3 + 1) = 2 x (2 x (2 x 1 + 1) + 1) = 2 x (2 x (2 x (2 x 0 + 1)) + 1) + 1) = 2^3 + 2^2 + 2
代码是上述算法的实现。
def toBaseX(n, X):
strbin = ""
while n != 0:
strbin += str(n % X)
n = n // X
return strbin[::-1]
答案 18 :(得分:0)
这里是如何将任意基数转换为另一基数的示例。
from collections import namedtuple
Test = namedtuple("Test", ["n", "from_base", "to_base", "expected"])
def convert(n: int, from_base: int, to_base: int) -> int:
digits = []
while n:
(n, r) = divmod(n, to_base)
digits.append(r)
return sum(from_base ** i * v for i, v in enumerate(digits))
if __name__ == "__main__":
tests = [
Test(32, 16, 10, 50),
Test(32, 20, 10, 62),
Test(1010, 2, 10, 10),
Test(8, 10, 8, 10),
Test(150, 100, 1000, 150),
Test(1500, 100, 10, 1050000),
]
for test in tests:
result = convert(*test[:-1])
assert result == test.expected, f"{test=}, {result=}"
print("PASSED!!!")
答案 19 :(得分:0)
我亲自使用我编写的此功能
import string
def to_base(value, base, digits=string.digits+string.ascii_letters): # converts decimal to base n
digits_slice = digits[0:base]
temporary_var = value
data = [temporary_var]
while True:
temporary_var = temporary_var // base
data.append(temporary_var)
if temporary_var < base:
break
result = ''
for each_data in data:
result += digits_slice[each_data % base]
result = result[::-1]
return result
这是使用它的方式
print(to_base(7, base=2))
输出:
"111"
print(to_base(23, base=3))
输出:
"212"
请随时提出改进建议。
答案 20 :(得分:0)
这是我的方法。首先转换数字然后将其转换为字符串。
def to_base(n, base):
if base == 10:
return n
result = 0
counter = 0
while n:
r = n % base
n //= base
result += r * 10**counter
counter+=1
return str(result)
答案 21 :(得分:0)
这是一个处理有符号整数和自定义数字的递归版本。
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]
答案 22 :(得分:0)
另一种解决方案,与基数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
答案 23 :(得分:0)
另一个简短的(更容易理解imo):
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")
答案 24 :(得分:0)
def baseConverter(x, b):
s = ""
d = string.printable.upper()
while x > 0:
s += d[x%b]
x = x / b
return s[::-1]
答案 25 :(得分:0)
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)
答案 26 :(得分:-1)
我还没有看到任何浮动转换器。我错过了总是三位数的分组。
TODO:
- 科学表达式(n.nnnnnn*10**(exp)
中的数字 - '10'
为self.baseDigits[1::-1]/self.to_string(len (self.baseDigits))
-from_string功能。
-base 1 - &gt;罗马数字?
与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)
答案 27 :(得分:-1)
字符串不是表示数字的唯一选择:您可以使用整数列表来表示每个数字的顺序。这些可以很容易地转换为字符串。
没有一个答案拒绝基础&lt; 2;对于非常大的数字(例如56789 ** 43210),大多数将运行非常缓慢或崩溃,堆栈溢出。为了避免这种失败,请迅速减少:
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)
纵向,n_to_base
与str
的大数字相当(在我的机器上约为0.3秒),但是如果你与hex
进行比较,你可能会感到惊讶(我的约0.3毫秒)机器,或快1000倍)。原因是因为大整数以256(字节)为基础存储在内存中。每个字节都可以简单地转换为双字符十六进制字符串。这种对齐只发生在2的幂的基数上,这就是为什么存在2,8和16(以及base64,ascii,utf16,utf32)的特殊情况。
考虑十进制字符串的最后一位数。它如何与形成整数的字节序列相关?让s[i]
标记字节s[0]
,其中sum([s[i]*(256**i) % 10 for i in range(n)])
是最不重要的(小端)。然后最后一位是(s[0]*5 + sum(s)*6)%10
。好吧,碰巧256 ** i以6结尾为i&gt; 0(6 * 6 = 36),以便最后一位为PUT /deploymentRequests/abcde
Please find the artifacts from build 12345 and deploy that artifact
to machine 67890
201 Created
。由此可以看出,最后一位数取决于所有字节的总和。这种非局部属性使得转换为十进制变得更难。
答案 28 :(得分:-1)
def base_conversion(num, base):
digits = []
while num > 0:
num, remainder = divmod(num, base)
digits.append(remainder)
return digits[::-1]
答案 29 :(得分:-1)
这是一个古老的问题,但是我想与我分享我的看法,因为我觉得其他答案要简单一些(适用于2到36的基数):
def intStr(n,base=10):
if n < 0 : return "-" + intStr(-n,base) # handle negatives
if n < base: return chr([48,55][n>9] + n) # 48 => "0"..., 65 => "A"...
return intStr(n//base,base) + intStr(n%base,base) # recurse for multiple digits
答案 30 :(得分:-1)
我知道这是一篇过时的文章,但是我只是将解决方案留在这里,以防万一。
def decimal_to_given_base(integer_to_convert, base):
remainder = integer_to_convert // base
digit = integer_to_convert % base
if integer_to_convert == 0:
return '0'
elif remainder == 0:
return str(digit)
else:
return decimal_to_given_base(remainder, base) + str(digit)
答案 31 :(得分:-1)
我发挥了作用。在Windows 10,Python 3.7.3上运行良好。
def number_to_base(number, base, precision = 10):
if number == 0:
return [0]
positive = number >= 0
number = abs(number)
ints = [] # store the integer bases
floats = [] # store the floating bases
float_point = number % 1
number = int(number)
while number:
ints.append(int(number%base))
number //= base
ints.reverse()
while float_point and precision:
precision -= 1
float_point *= base
floats.append(int(float_point))
float_point = float_point - int(float_point)
return ints, floats, positive
def base_to_str(bases, string="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
"""bases is a two dimension list, where bases[0] contains a list of the integers,
and bases[1] contains a list of the floating numbers, bases[2] is a boolean, that's
true when it's a positive number
"""
ints = []
floats = []
for i in bases[0]:
ints.append(string[i])
for i in bases[1]:
floats.append(string[i])
if len(bases[1]) > 0:
return (["-", ""][bases[2]] + "".join(ints)) + "." + ("".join(floats))
else:
return (["-", ""][bases[2]] + "".join(ints))
示例:
>>> base_to_str(number_to_base(-6.252, 2))
'-110.0100000010'
答案 32 :(得分:-2)
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
转换为任何基数,逆也很容易。