将可变大小的字节数组转换为整数长整数

将可变大小的字节数组转换为整数长整数,第1张

将可变大小的字节数组转换为整数/长整数

传统上,Python对于“大尾数C布局中的数字”用处不大,而对于C来说则用不了太多。(如果要处理2字节,4字节或8字节的数字,那么

struct.unpack
答案就是)

但是足够多的人厌倦了没有一种明显的方法可以做到这一点,Python
3.2添加了一种

int.from_bytes
完全可以实现您想要的方法:

int.from_bytes(b, byteorder='big', signed=False)

不幸的是,如果您使用的是旧版本的Python,则没有此功能。那么,您有什么选择?(除了显而易见的一个:更新为3.2,或者更好的是3.4…)


首先,有您的代码。我认为

binascii.hexlify
它是比esb更好的拼写方式
.enpre('hex')
,因为“
enpre”对于字节串(相对于Unipre字符串)的方法似乎总是有些怪异,并且实际上已在Python
3中被淘汰了。但是,否则,似乎可读性强,对我来说很明显。而且它应该非常快-
是的,它必须创建一个中间字符串,但是它正在C中进行所有循环和算术运算(至少在CPython中),这通常比Python快一两个数量级。除非您
bytearray
太大,以至于分配字符串本身都会很昂贵,否则我在这里不必担心性能。

或者,您可以循环执行。但这将更加冗长,至少在CPython中要慢得多。

您可以尝试消除一个隐式循环的显式循环,但是这样做的明显功能是

reduce
,在社区中,这被视为非Python的—当然,这将需要为每个字节调用一个函数。

您可以展开循环,也

reduce
可以将其分解为8个字节的块并进行循环
struct.unpack_from
,或者通过做一个大的
struct.unpack('Q'*len(b)//8+ 'B' * len(b)%8)
循环来进行循环,但这会使它的可读性大大降低,并且可能并没有那么快。

您可以使用NumPy…,但是如果您要大于64位或128位,则最终将所有内容都转换为Python对象。

因此,我认为您的答案是最好的选择。


以下是一些将其与最明显的手动转换进行比较的时间:

import binasciiimport functoolsimport numpy as npdef hexint(b):    return int(binascii.hexlify(b), 16)def loop1(b):    def f(x, y): return (x<<8)|y    return functools.reduce(f, b, 0)def loop2(b):    x = 0    for c in b:        x <<= 8        x |= c    return xdef numpily(b):    n = np.array(list(b))    p = 1 << np.arange(len(b)-1, -1, -1, dtype=object)    return np.sum(n * p)

In [226]: b = bytearray(range(256))In [227]: %timeit hexint(b)1000000 loops, best of 3: 1.8 µs per loopIn [228]: %timeit loop1(b)10000 loops, best of 3: 57.7 µs per loopIn [229]: %timeit loop2(b)10000 loops, best of 3: 46.4 µs per loopIn [283]: %timeit numpily(b)10000 loops, best of 3: 88.5 µs per loop

为了在Python 3.4中进行比较:

In [17]: %timeit hexint(b)1000000 loops, best of 3: 1.69 µs per loopIn [17]: %timeit int.from_bytes(b, byteorder='big', signed=False)1000000 loops, best of 3: 1.42 µs per loop

因此,您的方法仍然相当快……



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5645912.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存