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安全字符串?


当前回答

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

其他回答

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

我为此做了一个小包裹。

我建议你使用我的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

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

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”

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

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

没有一个答案拒绝底数< 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.

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