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


202

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

int(str, base). 

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

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

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

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

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

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

  • 这些功能在旧版本的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.base2baseconv.base16baseconv.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.