Python允许从给定基数的字符串中轻松创建一个整数

int(str, base). 

我想执行相反的操作:从一个整数创建一个字符串, 例如,我想要一些函数int2base(num, base),这样:

int(int2base(x, b), b) == x

函数名/参数的顺序并不重要。

对于int()将接受的任何以b为底的数字x。

这是一个很容易写的函数:事实上,它比在这个问题中描述它更容易。然而,我觉得我一定是错过了什么。

我知道函数bin, oct, hex,但我不能使用它们的几个原因:

这些函数在旧版本的Python中不可用,我需要与(2.2)兼容 我想要一个通解对于不同的碱都可以用同样的方式表示 我想允许2 8 16以外的底数

相关的

Python优雅的int(string, base)逆函数 在python中使用递归的整数到base-x系统 Python中的Base 62转换 如何在Python中将整数转换为最短的url安全字符串?


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

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

对于非常大的整数。


如果你需要兼容Python的古老版本,你可以使用gmpy(它包含一个快速的,完全通用的int-to-string转换函数,可以为这样的古老版本构建-你可能需要尝试更老的版本,因为最近的版本还没有针对古老的Python和GMP版本进行测试,只有一些最近的版本),或者,为了速度较慢但更方便,使用Python代码-例如,对于Python 2,最简单的方法是:

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)

对于Python 3, int(x / base)会导致不正确的结果,必须将其更改为x // base:

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[x % base])
        x = x // base

    if sign < 0:
        digits.append('-')

    digits.reverse()

    return ''.join(digits)

>>> 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'

很棒的答案! 我想我问题的答案是“不”,我并没有错过一些明显的解决方案。 下面是我将使用的函数,它可以浓缩答案中所表达的好想法。

允许调用者提供的字符映射(允许base64编码) 检查负数和零 将复数映射为字符串元组

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


"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144

您可以使用我的项目中的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。


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)

输出:

“1 f”


一个递归的解决方案。当然,这对负二进制值不起作用。您需要实现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

令人惊讶的是,人们给出的答案只能转换成小基数(比英语字母表的长度还小)。没有人试图给出一个可以转换为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],

你以后可以把它转换成任何你想要的基数

at some point of time you will notice that sometimes there is no built-in library function to do things that you want, so you need to write your own. If you disagree, post you own solution with a built-in function which can convert a base 10 number to base 577. this is due to lack of understanding what a number in some base means. I encourage you to think for a little bit why base in your method works only for n <= 36. Once you are done, it will be obvious why my function returns a list and has the signature it has.


我为此做了一个小包裹。

我建议你使用我的bases.py https://github.com/kamijoutouma/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/kamijoutouma/bases.py#known-basesalphabets 哪些基是可用的

编辑: PIP link https://pypi.python.org/pypi/bases.py/0.2.2


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 baseConverter(x, b):
    s = ""
    d = string.printable.upper()
    while x > 0:
        s += d[x%b]
        x = x / b
    return s[::-1]

另一个简短的(在我看来更容易理解):

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

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…“任务”是找出所有的a。

everyN = 1、2、3……代码通过b对b=base**(N+1)进行“模组”来隔离aN*base**N, b=base**(N+1)切片所有大于N的a,并通过每次由当前aN*base**N调用func时减少a来切片它们的序列小于N的所有a。

底%(底-1)==1,则底**p%(底-1)==1,而底q*底^p%(底-1)==q,只有当q=底-1时例外,返回0。 为了解决这个问题,如果它返回0,func会检查它从原点开始是否是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]

字符串不是表示数字的唯一选择:您可以使用一个整数列表来表示每个数字的顺序。这些可以很容易地转换为字符串。

没有一个答案拒绝底数< 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对于较大的数字(在我的机器上约为0.3秒)与str相当,但如果与十六进制进行比较,您可能会感到惊讶(在我的机器上约为0.3毫秒,或快1000倍)。这是因为大整数以256(字节)为基数存储在内存中。每个字节可以简单地转换为两个字符的十六进制字符串。这种对齐只发生在底数为2的幂的情况下,这就是为什么有2、8和16(以及base64, ascii, utf16, utf32)的特殊情况。

Consider the last digit of a decimal string. How does it relate to the sequence of bytes that forms its integer? Let's label the bytes s[i] with s[0] being the least significant (little endian). Then the last digit is sum([s[i]*(256**i) % 10 for i in range(n)]). Well, it happens that 256**i ends with a 6 for i > 0 (6*6=36) so that last digit is (s[0]*5 + sum(s)*6)%10. From this, you can see that the last digit depends on the sum of all the bytes. This nonlocal property is what makes converting to decimal harder.


num = input("number")
power = 0
num = int(num)
while num > 10:
    num = num / 10
    power += 1

print(str(round(num, 2)) + "^" + str(power))

递归

我将投票最多的答案简化为:

BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(n, b): 
    return "0" if not n else to_base(n//b, b).lstrip("0") + BS[n%b]

对于RuntimeError有相同的建议:对于非常大的整数和负数,在cmp中超过最大递归深度。(你可以使用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'

注意,numpy.base_repr()的基数限制为36。否则抛出ValueError


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]   

我个人使用我写的这个函数

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

你可以这样使用它

基础= 2)打印(to_base(7日)

输出: “111”

基础= 3)打印(to_base(23日)

输出: “212”

请随时对我的代码提出改进建议。


下面是一个如何将任意基数转换为另一个基数的示例。

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!!!")

def base_conversion(num, base):
    digits = []
    while num > 0:
        num, remainder = divmod(num, base)
        digits.append(remainder)
    return digits[::-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

我知道这是一个老帖子,但我只是把我的解决方案留在这里以防万一。

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)

我让函数这样做。在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'

假设我们想把14转换成2进制。我们反复应用除法算法,直到商为0:

14 = 2 × 7

7 = 2 × 3 + 1

3 = 2 × 1 + 1

1 = 2 × 0 + 1

二进制表示就是从下往上读的余数。这可以通过展开来证明

14 = 2 × 7 = 2 × (2 × 3 + 1) = 2 × (2 × (2 × 1 + 1) + 1) = 2 × (2 × (2 × 0 + 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]

这就是我的方法。首先转换数字,然后将其转换为字符串。

    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)

我写了这个函数,我用它来编码不同的碱基。我还提供了通过值“offset”来移动结果的方法。如果你想编码到64进制以上,但保持可显示字符(如95进制),这是有用的。

我还试图避免反转输出“列表”,并尽量减少计算操作。pow(base)数组是根据需要计算的,并保留用于对函数的其他调用。

输出是一个二进制字符串

pows = {}

######################################################
def encode_base(value,
                base = 10,
                offset = 0) :

    """
    Encode value into a binary string, according to the desired base.

    Input :
        value : Any positive integer value
        offset : Shift the encoding (eg : Starting at chr(32))
        base : The base in which we'd like to encode the value

    Return : Binary string

    Example : with : offset = 32, base = 64

              100 -> !D
              200 -> #(
    """

    # Determine the number of loops
    try :
        pb = pows[base]

    except KeyError :
        pb = pows[base] = {n : base ** n for n in range(0, 8) if n < 2 ** 48 -1}

    for n in pb :
        if value < pb[n] :
            n -= 1
            break

    out = []
    while n + 1 :
        b = pb[n]
        out.append(chr(offset + value // b))
        n -= 1
        value %= b

    return ''.join(out).encode()

这个函数将任意整数从任意进制转换为任意进制

def baseconvert(number, srcbase, destbase):
    if srcbase != 10:
        sum = 0
        for _ in range(len(str(number))):
            sum += int(str(number)[_]) * pow(srcbase, len(str(number)) - _ - 1)
        b10 = sum
        return baseconvert(b10, 10, destbase)
    end = ''
    q = number
    while(True):
        r = q % destbase
        q = q // destbase
        end = str(r) + end
        if(q<destbase):
            end = str(q) + end
            return int(end)

The below provided Python code converts a Python integer to a string in arbitrary base ( from 2 up to infinity ) and works in both directions. So all the created strings can be converted back to Python integers by providing a string for N instead of an integer. The code works only on positive numbers by intention (there is in my eyes some hassle about negative values and their bit representations I don't want to dig into). Just pick from this code what you need, want or like, or just have fun learning about available options. Much is there only for the purpose of documenting all the various available approaches ( e.g. the Oneliner seems not to be fast, even if promised to be ).

我喜欢萨尔瓦多·达利提出的无限大基地的格式。一个很好的建议,它在光学上工作得很好,即使是简单的二进制位表示。注意,在infiniteBase=True格式的字符串的情况下,width=x填充参数适用于数字,而不是整个数字。似乎,代码处理无穷大数字格式运行甚至比其他选项快一点-使用它的另一个原因?

我不喜欢使用Unicode来扩展数字可用的符号数量的想法,所以不要在下面的代码中寻找它,因为它不存在。请使用建议的infiniteBase格式,或者将整数存储为字节以进行压缩。

    def inumToStr( N, base=2, width=1, infiniteBase=False,\
    useNumpy=False, useRecursion=False, useOneliner=False, \
    useGmpy=False, verbose=True):
    ''' Positive numbers only, but works in BOTH directions.
    For strings in infiniteBase notation set for bases <= 62 
    infiniteBase=True . Examples of use:
    inumToStr( 17,  2, 1, 1)             # [1,0,0,0,1]
    inumToStr( 17,  3, 5)                #       00122
    inumToStr(245, 16, 4)                #        00F5
    inumToStr(245, 36, 4,0,1)            #        006T
    inumToStr(245245245245,36,10,0,1)    #  0034NWOQBH
    inumToStr(245245245245,62)           #     4JhA3Th 
        245245245245 == int(gmpy2.mpz('4JhA3Th',62))
    inumToStr(245245245245,99,2) # [25,78, 5,23,70,44]
    ----------------------------------------------------
    inumToStr( '[1,0,0,0,1]',2, infiniteBase=True ) # 17 
    inumToStr( '[25,78, 5,23,70,44]', 99) # 245245245245
    inumToStr( '0034NWOQBH', 36 )         # 245245245245 
    inumToStr( '4JhA3Th'   , 62 )         # 245245245245
    ----------------------------------------------------
    --- Timings for N = 2**4096, base=36: 
                                      standard: 0.0023
                                      infinite: 0.0017
                                      numpy   : 0.1277
                                      recursio; 0.0022
                                      oneliner: 0.0146
                For N = 2**8192: 
                                      standard: 0.0075
                                      infinite: 0.0053
                                      numpy   : 0.1369
    max. recursion depth exceeded:    recursio/oneliner
    '''
    show = print
    if type(N) is str and ( infiniteBase is True or base > 62 ):
        lstN = eval(N)
        if verbose: show(' converting a non-standard infiniteBase bits string to Python integer')
        return sum( [ item*base**pow for pow, item in enumerate(lstN[::-1]) ] )
    if type(N) is str and base <= 36:
        if verbose: show('base <= 36. Returning Python int(N, base)')
        return int(N, base)
    if type(N) is str and base <= 62:
        if useGmpy: 
            if verbose: show(' base <= 62, useGmpy=True, returning int(gmpy2.mpz(N,base))')
            return int(gmpy2.mpz(N,base))
        else:
            if verbose: show(' base <= 62, useGmpy=False, self-calculating return value)')
            lstStrOfDigits="0123456789"+ \
                "abcdefghijklmnopqrstuvwxyz".upper() + \
                "abcdefghijklmnopqrstuvwxyz"
            dictCharToPow = {}
            for index, char in enumerate(lstStrOfDigits):
                dictCharToPow.update({char : index}) 
            return sum( dictCharToPow[item]*base**pow for pow, item in enumerate(N[::-1]) )
        #:if
    #:if        
        
    if useOneliner and base <= 36:  
        if verbose: show(' base <= 36, useOneliner=True, running the Oneliner code')
        d="0123456789abcdefghijklmnopqrstuvwxyz"
        baseit = lambda a=N, b=base: (not a) and d[0]  or \
        baseit(a-a%b,b*base)+d[a%b%(base-1) or (a%b) and (base-1)]
        return baseit().rjust(width, d[0])[1:]

    if useRecursion and base <= 36: 
        if verbose: show(' base <= 36, useRecursion=True, running recursion algorythm')
        BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        def to_base(n, b): 
            return "0" if not n else to_base(n//b, b).lstrip("0") + BS[n%b]
        return to_base(N, base).rjust(width,BS[0])
        
    if base > 62 or infiniteBase:
        if verbose: show(' base > 62 or infiniteBase=True, returning a non-standard digits string')
        # Allows arbitrary large base with 'width=...' 
        # applied to each digit (useful also for bits )
        N, digit = divmod(N, base)
        strN = str(digit).rjust(width, ' ')+']'
        while N:
            N, digit = divmod(N, base)
            strN = str(digit).rjust(width, ' ') + ',' + strN
        return '[' + strN
    #:if        
    
    if base == 2:
        if verbose: show(" base = 2, returning Python str(f'{N:0{width}b}')")
        return str(f'{N:0{width}b}')
    if base == 8:
        if verbose: show(" base = 8, returning Python str(f'{N:0{width}o}')")
        return str(f'{N:0{width}o}')
    if base == 16:
        if verbose: show(" base = 16, returning Python str(f'{N:0{width}X}')")
        return str(f'{N:0{width}X}')

    if base <= 36:
        if useNumpy: 
            if verbose: show(" base <= 36, useNumpy=True, returning np.base_repr(N, base)")
            import numpy as np
            strN = np.base_repr(N, base)
            return strN.rjust(width, '0') 
        else:
            if verbose: show(' base <= 36, useNumpy=False, self-calculating return value)')
            lstStrOfDigits="0123456789"+"abcdefghijklmnopqrstuvwxyz".upper()
            strN = lstStrOfDigits[N % base] # rightmost digit
            while N >= base:
                N //= base # consume already converted digit
                strN = lstStrOfDigits[N % base] + strN # add digits to the left
            #:while
            return strN.rjust(width, lstStrOfDigits[0])
        #:if
    #:if
    
    if base <= 62:
        if useGmpy: 
            if verbose: show(" base <= 62, useGmpy=True, returning gmpy2.digits(N, base)")
            import gmpy2
            strN = gmpy2.digits(N, base)
            return strN.rjust(width, '0') 
            # back to Python int from gmpy2.mpz with 
            #     int(gmpy2.mpz('4JhA3Th',62))
        else:
            if verbose: show(' base <= 62, useGmpy=False, self-calculating return value)')
            lstStrOfDigits= "0123456789" + \
                "abcdefghijklmnopqrstuvwxyz".upper() + \
                "abcdefghijklmnopqrstuvwxyz"
            strN = lstStrOfDigits[N % base] # rightmost digit
            while N >= base:
                N //= base # consume already converted digit
                strN = lstStrOfDigits[N % base] + strN # add digits to the left
            #:while
            return strN.rjust(width, lstStrOfDigits[0])
        #:if
    #:if    
#:def

我提出了一个“非优化”的2到9基的解决方案:

  def to_base(N, base=2):
    N_in_base = ''
    while True:
        N_in_base = str(N % base) + N_in_base
        N //= base
        if N == 0:
            break
    return N_in_base

这个解决方案不需要反转最终结果,但实际上并没有优化。请参考以下答案了解原因:https://stackoverflow.com/a/37133870/7896998


简单基底变换

def int_to_str(x, b):
    s = ""
    while x:
        s = str(x % b) + s
        x //= b
    return s

输出的例子,没有0到基数9

s = ""
x = int(input())
while x:
    if x % 9 == 0:
        s = "9" + s
        x -= x % 10
        x = x // 9
    else:
        s = str(x % 9) + s
        x = x // 9

print(s)

虽然目前排名第一的答案绝对是一个很棒的解决方案,但仍然有更多用户可能喜欢的定制。

Basencode添加了其中的一些特性,包括浮点数的转换、修改数字(在链接的答案中,只能使用数字)。

下面是一个可能的用例:

>>> from basencode import *
>>> n1 = Number(12345)
>> n1.repr_in_base(64) # convert to base 64
'30V'
>>> Number('30V', 64) # construct Integer from base 64
Integer(12345)
>>> n1.repr_in_base(8)
'30071'
>>> n1.repr_in_octal() # shortcuts
'30071'
>>> n1.repr_in_bin() # equivelant to `n1.repr_in_base(2)`
'11000000111001'
>>> n1.repr_in_base(2, digits=list('-+')) # override default digits: use `-` and `+` in place of `0` and `1`
'++------+++--+'
>>> n1.repr_in_base(33) # yet another base - all bases from 2 to 64 are supported from the start
'bb3'

你怎么添加你想要的碱基?让我复制一下目前投票最多的答案的例子:digits参数允许您覆盖从2到64的默认数字,并为任何高于该基数的数字提供数字。mode参数决定了表示的值如何决定(列表或字符串)如何返回答案。

>>> n2 = Number(67854 ** 15 - 102)
>>> n2.repr_in_base(577, digits=[str(i) for i in range(577)], mode="l")
['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']
>>> n2.repr_in_base(577, mode="l") # the program remembers the digits for base 577 now
['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']

可以执行以下操作:Number类返回basencode的一个实例。如果提供的数字是Integer,则返回一个基本编码。浮动

>>> n3 = Number(54321) # the Number class returns an instance of `basencode.Integer` if the provided number is an Integer, otherwise it returns a `basencode.Float`.
>>> n1 + n3
Integer(66666)
>>> n3 - n1
Integer(41976)
>>> n1 * n3
Integer(670592745)
>>> n3 // n1
Integer(4)
>>> n3 / n1 # a basencode.Float class allows conversion of floating point numbers
Float(4.400243013365735)
>>> (n3 / n1).repr_in_base(32)
'4.cpr56v6rnc4oitoblha2r11sus0dheqd4pgechfcjklo74b2bgom7j8ih86mipdvss0068sehi9f3791mdo4uotfujq66cf0jkgo'
>>> n4 = Number(0.5) # returns a basencode.Float
>>> n4.repr_in_bin() # binary version of 0.5
'0.1'

免责声明:此项目正在积极维护中,我是贡献者。