我有这个Python代码:
from struct import pack as _pack
def packl(lnum, pad = 1):
if lnum < 0:
raise RangeError("Cannot use packl to convert a negative integer "
"to a string.")
count = 0
l = []
while lnum > 0:
l.append(lnum & 0xffffffffffffffffL)
count += 1
lnum >>= 64
if count <= 0:
return '\0' * pad
elif pad >= 8:
lens = 8 * count % pad
pad = ((lens != 0) and (pad - lens)) or 0
l.append('>' + 'x' * pad + 'Q' * count)
l.reverse()
return _pack(*l)
else:
l.append('>' + 'Q' * count)
l.reverse()
s = _pack(*l).lstrip('\0')
lens = len(s)
if (lens % pad) != 0:
return '\0' * (pad - lens % pad) + s
else:
return s
在我的机器上,将2**9700 - 1
转换为一个字节字符串大约需要174 usec。如果我愿意使用Python 2.7和Python 3.x特定的bit_length
方法,我可以通过预先将l
数组在一开始就精确地分配为正确的大小,并使用l[something] =
语法而不是l.append
来将其缩短为159个usecs。
我能做些什么来加快速度吗?这将用于转换加密中使用的大素数以及一些(但不是很多)较小的数。
编辑
这是Python<;3.2中当前速度最快的选项,接受答案的时间大约是两个方向的一半:
def packl(lnum, padmultiple=1):
"""Packs the lnum (which must be convertable to a long) into a
byte string 0 padded to a multiple of padmultiple bytes in size. 0
means no padding whatsoever, so that packing 0 result in an empty
string. The resulting byte string is the big-endian two's
complement representation of the passed in long."""
if lnum == 0:
return b'\0' * padmultiple
elif lnum < 0:
raise ValueError("Can only convert non-negative numbers.")
s = hex(lnum)[2:]
s = s.rstrip('L')
if len(s) & 1:
s = '0' + s
s = binascii.unhexlify(s)
if (padmultiple != 1) and (padmultiple != 0):
filled_so_far = len(s) % padmultiple
if filled_so_far != 0:
s = b'\0' * (padmultiple - filled_so_far) + s
return s
def unpackl(bytestr):
"""Treats a byte string as a sequence of base 256 digits
representing an unsigned integer in big-endian format and converts
that representation into a Python integer."""
return int(binascii.hexlify(bytestr), 16) if len(bytestr) > 0 else 0
在Python 3.2中,int
类有to_bytes
和from_bytes
函数,它们可以比上面给出的方法更快地实现这一点。
我想你真的应该使用numpy,我肯定它有一些内置的东西。使用
array
模块也可能更快。但我还是要试试看。IMX,创建一个生成器并使用一个列表理解和/或内置求和比附加到列表的循环快,因为附加可以在内部完成。哦,而且大绳上的“lstrip”一定很贵。
另外,一些样式点:特殊情况不够特殊;而且您似乎没有得到关于新
x if y else z
构造的备忘录。:)尽管我们不需要它。;)这里有一个通过
ctypes
调用Python/C API的解决方案。目前,它使用的是NumPy,但如果NumPy不是一个选项,那么它完全可以使用ctypes
来完成。在我的机器上,这比你的方法快15倍。
编辑:这里是相同的代码,只使用
ctypes
,返回字符串而不是NumPy数组:这是另外两倍的速度,在我的机器上总共是30倍的加速系数。
为了完整起见,也为了将来读者了解这个问题:
从Python 3.2开始,有一些函数^{} 和^{} 以字节顺序的选择执行
bytes
和int
对象之间的转换。相关问题 更多 >
编程相关推荐