如何将整数转换为任意基数的字符串?


202

Python允许通过给定基数的字符串通过以下方式轻松创建整数

int(str, base). 

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

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

函数名称/参数顺序不重要。

对于任何数量x和底座b是int()会接受的。

这是一个易于编写的函数:实际上,比在此问题中对其进行描述更容易。但是,我觉得我必须丢失一些东西。

我知道的功能bin,oct,hex,但我不能使用他们的几个原因:

  • 这些功能在旧版本的Python上不可用,我需要与这些版本兼容(2.2)

  • 我想要一个通用的解决方案,可以针对不同的基础使用相同的方式

  • 我想允许除2、8、16以外的其他基数

有关


5
出人意料的是,没有人提供可以在任意大基础上使用的解决方案(1023)。如果您需要它,请检查我的解决方案,该解决方案适用于每个基础(从2到inf)stackoverflow.com/a/28666223/1090562
— Salvador Dali

Answers:


98

如果您需要与Python的旧版本兼容,则可以使用gmpy(它确实包含了快速,完全通用的从int到字符串的转换功能,并且可以针对此类旧版本进行构建-您可能需要尝试使用较旧的版本,因为最近的版本尚未针对过时的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)

8
就在(gmpy2)情况下,Alex说过的功能似乎是gmpy2.digits(x, base)。
— mlvljr 2012年

2
它带给我的注意,有些情况下需要一个基地> 36等挖掘应该是digs = string.digits + string.lowercase + string.uppercase
— 保罗

4
(或string.digits + string.letters)
— kojiro 2013年

3
知道为什么Python默认不包含convert-base-N-to-string吗?是的,我们都可以编写我们自己的实现,但是我一直在这个站点和其他地方进行搜索,其中许多都有bug。最好在核心发行版中包含一个经过测试的信誉良好的版本。
— 杰森S

4
@ lordscales91您也可以在删除小数点时使用x //= base类似/=Python 2的行为。此答案应包括针对Python 2的免责声明
— 。– Noumenon

100

出乎意料的是,人们只给出了转换为较小基数(小于英文字母的长度)的解决方案。没有尝试给出一种可以将任何从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],

您以后可以将其转换为所需的任何基准


在大学里,我想到了一个函数,该函数将20以下的基数格式化为标准符号,然后将20以上的基数格式化为“冒号分隔的十进制”。例如,int(4545,16)给出“ 11c1”并int(4545,60)给出“ 1:15:45”。因此,该函数执行了三重任务:转换为十进制,计算机格式和时间戳格式。
— 彼得·雷纳姆

1
此方法的逆函数是什么?
— Sohrab T

这不会回答以下三个原因所引起的问题:1:询问现有库函数而不是实现2:询问字符串,这将产生一个列表3:这不是int(str,基本)内置。
— plugwash

@plugwash 1)在某个时间点,您会发现有时没有内置库函数可以执行所需的操作,因此您需要编写自己的函数。如果您不同意,请使用内置函数发布您自己的解决方案,该函数可以将以10为底的数字转换为以577为底的数字。2)这是由于缺乏对某个底数的含义的理解。3)我鼓励您花一点时间思考为什么方法中的base仅对n <= 36有效。完成后,很明显为什么我的函数返回一个列表并具有它的签名。
— 萨尔瓦多·达利

1
这不适用于负数,而且我不确定在不进行根本更改的情况下如何使其工作。也许在符号的顶部添加一个符号位1或-1 digits?
— wjandrea

89
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

对于非常大的整数。


5
简洁而优雅。对于非负整数,它似乎在python 2.2.3下工作。负数无限递归。
— Mark Borgerding 2010年

+1有用;解决了数字不是以“ 0”开头的问题
— sehe 2011年

4
(a)当base为>时len(numerals),这默默地失败了;而(b)num % b运气是< len(numerals)。例如,尽管numerals字符串的长度只有36个字符,但baseN(60,40)返回,'1k'而baseN(79,40)引发一个IndexError。两者都应引起某种错误。如果,应修改代码以引发错误not 2 <= base <= len(numerals)。
— 克里斯·约翰逊

3
@osa,我要指出的是,编写的代码以非常糟糕的方式失败(无声地给出错误的答案),并且可以轻松修复。如果您说如果您事先知道就不会有错误,可以肯定的是,这b不会超过len(numerals)您的好运。
— 克里斯·约翰逊

1
这里使用短路似乎不必要地造成混淆...为什么不仅仅使用if语句...该行return numerals[0] if num == 0 else baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b]也是如此简短。
— 伊恩·欣克斯

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

46
但这只是这三个基础吗?
— Thomas Ahle,

3
是的,很遗憾,您不能指定自定义int base。更多信息在这里:docs.python.org/library/string.html#formatstrings
— Rost,

3
这0是不必要的。这是Python 2文档:docs.python.org/2/library/string.html#format-string-syntax
— Evgeni Sergeev

7
你可以达到相同的结果hex(100)[2:],oct(100)[2:]和bin(100)[2:]。
— 萨桑

2
@EvgeniSergeev:仅在2.7 / 3.1 +上是不必要的。在2.6上,需要显式位置(或名称)。
— ShadowRanger

21

好答案!我想我的问题的答案是“不”,我没有错过一些明显的解决方案。这是我将使用的功能,它凝聚了答案中表达的好主意。

  • 允许调用者提供的字符映射(允许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


4
如何将函数的base64输出转换回整数?
— 熟练地

16

递归的

我想简化了最投票回答到:

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"

2
精美的重构,并且没有库。
— Giampaolo Ferradini

那么停止条件不应该return BS[0] if not n吗?万一您想像我一样使用花哨的数字:)
— Arnaud P

@ArnaudP同意。这对我return BS[n] if n < b else to_base(n // b) + BN[n % b]
— 詹斯


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。


12

>>> numpy.base_repr(10, base=3) '101'


不错的解决方案。就我而言,我避免了numpy clac的加载时间问题。预加载numpy会使clac中简单表达式求值的运行时间增加三倍:例如, clac 1+1 从大约40ms变为140ms。
— Mark Borgerding

1
请注意,numpy.base_repr()其上限为36。否则会在ValueError
— sbdchd

符合内置“ int”函数的限制。大基地需要决定何时字母用完了怎么办,
— plugwash

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

base10toN不占NUM的情况下== 0
— Craeft

3

我为此做了一个小包。

我建议您使用受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


对于指定的已知基准,这就像一个魅力。
— Agi Hammerthief,2016年

到目前为止,这是最好的答案!并感谢您的点子包装!
— ɹɐʎɯɐʞ

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”


other-base与相同other - base,因此您应使用other_base
— mbomb007

另外,如果decimal为零,这将无法正常工作。
— mbomb007

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'

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

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...。“任务”是找到所有的。

对于每N=1,2,3...一个代码,aN*base**N通过“模制” b来隔离a,b=base**(N+1) 将所有a大于N的切片“ b” 隔离 ,并通过每次调用func来减少其序列小于N的所有a的切片aN*base**N。

因此,base%(base-1)== 1 base ** p%(base-1)== 1并因此q * base ^ p%(base-1)== q,当q = base-1时只有一个例外它返回0。为解决万一返回0的问题,函子正在从开始检查它是​​否为0。


优点

在此样本中,只有一个乘法(而不是除法)和一些模数,这相对需要少量时间。


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

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

请添加一些简短的信息,说明您做了特殊的初始化
— Farhana

虽然这可以回答作者的问题,但缺少一些解释性的单词和/或指向文档的链接。如果没有原始代码段,则原始代码段不是很有帮助。您可能还会发现如何写一个好的答案很有帮助。请修改您的答案。
— hellow

1
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]   

在此功能中,您可以轻松地将任何十进制数字转换为您喜欢的基数。
— montaqami

您无需评论自己的答案,只需对其进行编辑即可添加说明。
— Pochmurnik

1

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

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

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)

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

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

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]

0

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

没有一个答案会拒绝基数<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)

Speedwise 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)])。好吧,对于i> 0(6 * 6 = 36),发生256 ** i以6结尾的情况是这样,所以最后一位是(s[0]*5 + sum(s)*6)%10。由此可见,最后一位取决于所有字节的总和。此非本地属性使转换为十进制变得更加困难。


0
def baseConverter(x, b):
    s = ""
    d = string.printable.upper()
    while x > 0:
        s += d[x%b]
        x = x / b
    return s[::-1]

对于python3,您的代码执行此操作:baseConverter(0,26)->''baseConverter(1,26)->'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'对于python2,它执行以下操作:baseConverter(0,26)->''baseConverter(1,26) -> 1 baseConverter(3,26)-> 3 baseConverter(5,26)-> 5 baseConverter(26,26)-> 10 baseConverter(32,26)-> 16
— Drachenfels

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"

请随时提出改进建议。


0
def base_conversion(num, base):
    digits = []
    while num > 0:
        num, remainder = divmod(num, base)
        digits.append(remainder)
    return digits[::-1]

0

这是一个古老的问题,但是我想与我分享我的看法,因为我认为其他答案要简单一些(适用于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

-1

我在这里没有看到任何float转换器。我错过了总是三位数的分组。

去做:

-值在科学的表达(n.nnnnnn*10**(exp)-的'10'是self.baseDigits[1::-1]/self.to_string(len (self.baseDigits))

-from_string-function。

-base 1->罗马数字?

-repr与agles的复合体

所以这是我的解决方案:

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)

-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

要转换为任何基数,逆也很容易。


得了NameError: global name 'n' is not defined。被divmod(x, n)认为是divmod(x, b)?
— wjandrea
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.