Python优雅的反函数int(string,base)
python允许使用范围[2,36]中的任何基数从string转换为整数:
int(string,base)
即时通讯寻找一个优雅的反function,采取一个整数和一个基地,并返回一个string
例如
>>> str_base(224,15) 'ee'
我有以下解决scheme:
def digit_to_char(digit): if digit < 10: return chr(ord('0') + digit) else: return chr(ord('a') + digit - 10) def str_base(number,base): if number < 0: return '-' + str_base(-number,base) else: (d,m) = divmod(number,base) if d: return str_base(d,base) + digit_to_char(m) else: return digit_to_char(m)
注意:digit_to_char()适用于base <= 169任意使用“z”后面的ascii字符作为36以上的数字
是否有一个Python内置的库函数,或者是一个更精致的int(string,base)的反函数?
这个线程有一些示例实现。
其实我认为你的解决scheme看起来相当不错,它甚至recursion,这在某种程度上是令人愉快的。
我仍然简化它去除else
,但这可能是一个个人风格的事情。 我想if foo: return
是非常清楚的,并且在它之后不需要else
来清楚它是一个单独的分支。
def digit_to_char(digit): if digit < 10: return str(digit) return chr(ord('a') + digit - 10) def str_base(number,base): if number < 0: return '-' + str_base(-number, base) (d, m) = divmod(number, base) if d > 0: return str_base(d, base) + digit_to_char(m) return digit_to_char(m)
我在digit_to_char()
简化了0-9的情况,我认为str()
比chr(ord())
结构更清晰。 为了最大化对称性>= 10
情况下, ord()
可以被分解出来,但我没有打扰,因为它会添加一条线,简洁感觉更好。 🙂
也许这不应该是一个答案,但它可能会有所帮助:内置的format
函数将数字转换为string在几个基地:
>>> format(255, 'b') # base 2 '11111111' >>> format(255, 'd') # base 10 '255' >>> format(255, 'o') # base 8 '377' >>> format(255, 'x') # base 16 'ff'
如果您使用Numpy,则有numpy.base_repr
。
您可以阅读numpy/core/numeric.py
下的代码。 短而优雅
上面的答案真的很好。 它帮助我创build了一个我必须在C中实现的algorithm
我想提出一点改变(我用)将十进制转换为符号空间的基础
我也忽略了negativ值只是为了简短和事实,是math不正确的 – >其他规则的模块化算术 – >其他math,如果你使用二进制,十进制或hex – >差异在无符号&有符号值
def str_base(number, base): (d,m) = divmod(number,len(base)) if d > 0: return str_base(d,base)+base[m] return base[m]
那导致跟随输出
>>> str_base(13,'01') '1101' >>> str_base(255,'01') '11111111' >>> str_base(255,'01234567') '377' >>> str_base(255,'0123456789') '255' >>> str_base(255,'0123456789abcdef') 'ff' >>> str_base(1399871903,'_helowrd') 'hello_world'
如果你想使用propper零符号,你可以使用
symbol_space = 'abcdest' >>> str_base(734,symbol_space).rjust(0,symbol_space[0]) 'catt' >>> str_base(734,symbol_space).rjust(6,symbol_space[0]) 'aacatt'
审查这个。
def int2str(num, base=16, sbl=None): if not sbl: sbl = '0123456789abcdefghijklmnopqrstuvwxyz' if len(sbl) < 2: raise ValueError, 'size of symbols should be >= 2' if base < 2 or base > len(sbl): raise ValueError, 'base must be in range 2-%d' % (len(sbl)) neg = False if num < 0: neg = True num = -num num, rem = divmod(num, base) ret = '' while num: ret = sbl[rem] + ret num, rem = divmod(num, base) ret = ('-' if neg else '') + sbl[rem] + ret return ret
digit_to_char
可以这样实现:
def digit_to_char(digit): return (string.digits + string.lowercase)[digit]
我曾经用相同的目标写过我自己的function,但现在令人尴尬的复杂。
from math import log, ceil, floor from collections import deque from itertools import repeat from string import uppercase, digits import re __alphanumerals = (digits + uppercase) class InvalidBaseError(ValueError): pass class FloatConvertError(ValueError): pass class IncorrectBaseError(ValueError): pass def getbase(number, base=2, frombase = 10): if not frombase == 10: number = getvalue(number, frombase) #getvalue is also a personal function to replicate int(number, base) if 1 >= base or base >= len(__alphanumerals) or not floor(base) == base: raise InvalidBaseError("Invalid value: {} entered as base to convert to. \n{}".format(base, "Assert that the base to convert to is a decimal integer.")) if isinstance(number, str): try: number = atof(number) except ValueError: #The first check of whether the base is 10 would have already corrected the number raise IncorrectBaseError("Incorrect base passed as base of number -> number: {} base: {}".format(number, frombase)) #^ v was supporting float numbers incase number was the return of another operation if number > floor(number): raise FloatConvertError("The number to be converted must not be a float. {}".format(number)) isNegative = False if number < 0: isNegative = True number = abs(number) logarithm = log(number, base) if number else 0 #get around number being zero easily ceiling = int(logarithm) + 1 structure = deque(repeat(0, ceiling), maxlen = ceiling) while number: if number >= (base ** int(logarithm)): acceptable_digit = int(number / (base ** floor(logarithm))) structure.append(acceptable_digit if acceptable_digit < 10 else __alphanumerals[acceptable_digit]) number -= acceptable_digit * (base ** floor(logarithm)) else: structure.append(0) logarithm -= 1 while structure[0] == 0: #the result needs trailing zeros structure.rotate(-1) return ("-" if isNegative and number else "") + reduce(lambda a, b: a + b, map(lambda a: str(a), structure))
我认为,虽然函数strbase应该只支持base> = 2和<= 36以防止在Python等其他工具与int的冲突。 另外,我认为只有一个字母应该再次使用大写,以防止与int等其他函数发生冲突,因为它会将“a”和“A”都视为10。
from string import uppercase dig_to_chr = lambda num: str(num) if num < 10 else uppercase[num - 10] def strbase(number, base): if not 2 <= base <= 36: raise ValueError("Base to convert to must be >= 2 and <= 36") if number < 0: return "-" + strbase(-number, base) d, m = divmod(number, base) if d: return strbase(d, base) + dig_to_chr(m) return dig_to_chr(m)
有一点Google使用这个 。 其中一个评论是关于Python内置函数的:
int(x [,base]) converts x to an integer long(x [,base]) converts x to a long integer float(x) converts x to a floating-point number complex(real [,imag]) creates a complex number chr(x) converts an integer to a character unichr(x) converts an integer to a Unicode character ord(c) converts a character to its integer value hex(x) converts an integer to a hexadecimal string oct(x) converts an integer to an octal string
但是他们中没有一个似乎是对的 我想你只需要编写自己的函数。 链接中有示例代码。
这是我的灵魂
def int2base(a, base, numerals="0123456789abcdefghijklmnopqrstuvwxyz"): baseit = lambda a=a, b=base: (not a) and numerals[0] or baseit(aa%b,b*base)+numerals[a%b%(base-1) or (a%b) and (base-1)] return baseit()
说明
在任何基数中,每个数字都等于a1+a2*base**2+a3*base**3...
“任务”是查找所有的a。
对于每个N=1,2,3...
代码是通过对于b=base**(N+1)
的b来“模糊”来隔离aN*base**N
,其中所有的a都大于N,并且通过每次减less当前的aN*base**N
调用func来将所有a的序列小于aN*base**N
基数%(base-1)== 1基数** p%(base-1)== 1且因此q * base ^ p%(base-1)== q只有当q = base-1返回0.为了解决这个问题,以防万一它返回0 func正在检查它是从0开始。
优点
在这个样本中只有一个乘法(而不是除法)和一些相对需要less量时间的模拟。