在Python2.x中使用标准库将字节数组转换为Int
我熟悉使用int.from bytes()进行Python 3.x和Bytearray到十进制的转换。可能会产生下面的转换代码段。对于正整数和负整数,有没有一种方法可以使用Python2实现相同的功能在Python2.x中使用标准库将字节数组转换为Int,python,python-3.x,python-2.7,Python,Python 3.x,Python 2.7,我熟悉使用int.from bytes()进行Python 3.x和Bytearray到十进制的转换。可能会产生下面的转换代码段。对于正整数和负整数,有没有一种方法可以使用Python2实现相同的功能 val = bytearray(b'\x8f\x0f\xfd\x02\xf4\x95s\x00\x00') a = int.from_bytes(val, byteorder='big', signed=True) # print(type(a), type(val), val, a) # &l
val = bytearray(b'\x8f\x0f\xfd\x02\xf4\x95s\x00\x00')
a = int.from_bytes(val, byteorder='big', signed=True)
# print(type(a), type(val), val, a)
# <class 'int'> <class 'bytearray'> bytearray(b'\x8f\x0f\xfd\x02\xf4\x95s\x00\x00') -2083330000000000000000
Python2.7中没有内置函数来实现3.2+中的
int.from_bytes
;这就是为什么首先添加了该方法
如果您不关心处理big-endian签名整数以外的任何情况,并且更关心可读性而不是性能(因此您可以自己扩展或维护它),最简单的解决方案可能是在字节上显式循环
对于未签名的,这将很容易:
n = 0
for by in b:
n = n * 256 + by
但要处理负数,您需要做三件事:
- 从最高字节中去掉符号位。因为我们只关心big-endian,所以这是
上的b[0]
位0x80
- 这使得空bytearray成为一种特殊情况,所以要特别处理它
- 最后,如果设置了符号位,则2的补码将得到结果
bytearray
和bytearray
;但不包括str
)
在Python 3中测试您的输入:
>>> for b in (bytearray(b'\x8f\x0f\xfd\x02\xf4\x95s\x00\x00'),
... bytearray(b'\x00'),
... bytearray(b'\xef\xbc\xa9\xe5w\xd6\xd0\x00\x00'),
... bytearray(b'\x10CV\x1a\x88)0\x00\x00')):
... print(int.from_bytes(b, 'big', signed=True), int_from_bytes(b))
-2083330000000000000000 -2083330000000000000000
0 0
-300000000000000000000 -300000000000000000000
300000000000000000000 300000000000000000000
在Python 2中:
>>> for b in (bytearray(b'\x8f\x0f\xfd\x02\xf4\x95s\x00\x00'),
... bytearray(b'\x00'),
... bytearray(b'\xef\xbc\xa9\xe5w\xd6\xd0\x00\x00'),
... bytearray(b'\x10CV\x1a\x88)0\x00\x00')):
... print int_from_bytes(b)
-2083330000000000000000
0
-300000000000000000000
300000000000000000000
如果这是一个瓶颈,那么几乎肯定有更快的方法来实现这一点。例如,可以通过
gmpy2
。事实上,即使将字节转换为十六进制字符串并取消验证也可能会更快,即使这项工作是原来的两倍多,如果您可以找到一种方法将这些主循环从Python移动到C。或者您可以合并调用struct.unpack的结果,每次从中解包8个字节,而不是逐个处理每个字节。但是这个版本应该很容易理解和维护,并且不需要stdlib之外的任何东西。Python 2.7中没有内置函数来实现3.2+中的int.from_bytes
;这就是为什么首先添加了该方法
如果您不关心处理big-endian签名整数以外的任何情况,并且更关心可读性而不是性能(因此您可以自己扩展或维护它),最简单的解决方案可能是在字节上显式循环
对于未签名的,这将很容易:
n = 0
for by in b:
n = n * 256 + by
但要处理负数,您需要做三件事:
- 从最高字节中去掉符号位。因为我们只关心big-endian,所以这是
b[0]
上的0x80
位
- 这使得空bytearray成为一种特殊情况,所以要特别处理它
- 最后,如果设置了符号位,则2的补码将得到结果
因此:
(在Python3中,它适用于任何一个整数的iterable。在Python2中,它包括bytearray
和bytearray
;但不包括str
)
在Python 3中测试您的输入:
>>> for b in (bytearray(b'\x8f\x0f\xfd\x02\xf4\x95s\x00\x00'),
... bytearray(b'\x00'),
... bytearray(b'\xef\xbc\xa9\xe5w\xd6\xd0\x00\x00'),
... bytearray(b'\x10CV\x1a\x88)0\x00\x00')):
... print(int.from_bytes(b, 'big', signed=True), int_from_bytes(b))
-2083330000000000000000 -2083330000000000000000
0 0
-300000000000000000000 -300000000000000000000
300000000000000000000 300000000000000000000
在Python 2中:
>>> for b in (bytearray(b'\x8f\x0f\xfd\x02\xf4\x95s\x00\x00'),
... bytearray(b'\x00'),
... bytearray(b'\xef\xbc\xa9\xe5w\xd6\xd0\x00\x00'),
... bytearray(b'\x10CV\x1a\x88)0\x00\x00')):
... print int_from_bytes(b)
-2083330000000000000000
0
-300000000000000000000
300000000000000000000
如果这是一个瓶颈,那么几乎肯定有更快的方法来实现这一点。例如,可以通过gmpy2
。事实上,即使将字节转换为十六进制字符串并取消验证也可能会更快,即使这项工作是原来的两倍多,如果您可以找到一种方法将这些主循环从Python移动到C。或者您可以合并调用struct.unpack的结果,每次从中解包8个字节,而不是逐个处理每个字节。但是这个版本应该易于理解和维护,并且不需要stdlib之外的任何东西。您可能最好使用pack
来实现这一点。实际上,我已经很惊讶Python-3.x能做到这一点,因为在Python-3.x中,int
具有任意大小。当然,威廉。我们现在将查看文档。BT会处理签名的BtoTuriar到int转换,还是只有正整数?在发布之前,考虑复制并粘贴到谷歌搜索栏中。我使用的是Python 3.6.1 | Anaconda 4.4.0。当我在我的更高版本的Python中本地尝试此代码段时,它可以工作,但在2.7中却不能。对此,您可能最好使用pack
。实际上,我已经很惊讶Python-3.x会这样做,因为在Python-3.x中,int
具有任意大小。当然,Willem。我们现在将查看文档。BT会处理签名的BtoTuriar到int转换,还是只有正整数?在发布之前,考虑复制并粘贴到谷歌搜索栏中。我使用的是Python 3.6.1 | Anaconda 4.4.0。当我在更高版本的Python中本地尝试此代码段时,它可以工作,但在2.7中却不能。非常感谢……)工作顺利。也修改了问题标题@版主请随时更新它,如果它仍然似乎是误导。abarnert为具有类似要求的ppl编写的漂亮代码段。对于记录,转换为十六进制和解析要快得多int(binascii.hexlify(mybytes),16)
非常快(我以前有理由重新发明这个,这个解决方案比任何其他选项都快几个数量级)。非常感谢:)工作顺利。也修改了问题标题@版主请随时更新它,如果它仍然似乎是误导。abarnert为具有类似要求的ppl编写的漂亮代码段。对于记录,转换为十六进制和解析要快得多int(binascii.hexlify(mybytes),16)
真的很快(我以前有理由重新发明这个,这个解决方案比任何其他选项都快几个数量级)。