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


当前回答

如果你需要兼容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)

其他回答

我提出了一个“非优化”的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

我为此做了一个小包裹。

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

假设我们想把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]

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

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'

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

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

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)