在python中将64位整数转换为8个单独的1字节整数

JHi*_*son 12 python bitmask

在python中,我得到了一个64位整数.这个Integer是通过采用几个不同的8位整数并将它们拼接成一个巨大的64位整数而创建的.我的工作是再次分开他们.

例如:

Source number: 2592701575664680400
Binary (64 bits): 0010001111111011001000000101100010101010000101101011111000000000
int 1: 00100011 (35)
int 2: 11111011 (251)
int 3: 00100000 (32)
int 4: 01011000 (88)
int 5: 10101010 (170)
int 6: 00010110 (22)
int 7: 10111110 (190)
int 8: 00000000 (0)
Run Code Online (Sandbox Code Playgroud)

所以我想做的是获取我的源编号2592701575664680373并返回一个长度为8的数组,其中数组中的每个int都是上面列出的int.

我本来打算使用struct,但说实话,阅读文档并没有清楚地说明我将如何实现这一目标.

joj*_*nas 9

没有将数字转换为字符串的解决方案:

x = 0b0010001111111011001000000101100010101010000101101011111000000000

numbers = list((x >> i) & 0xFF for i in range(0,64,8))
print(numbers)                    # [0, 190, 22, 170, 88, 32, 251, 35]
print(list(reversed(numbers)))    # [35, 251, 32, 88, 170, 22, 190, 0]
Run Code Online (Sandbox Code Playgroud)

说明

在这里,我使用了列表推导,以8的增量进行循环i.所以i取值0, 8, 16, 24, 32, 40, 48, 56.每次,bitshift运算符>>暂时将数字x逐位移i位.这相当于除以256^i.

所以得到的数字是:

i = 0:   0010001111111011001000000101100010101010000101101011111000000000
i = 8:           00100011111110110010000001011000101010100001011010111110
i = 16:                  001000111111101100100000010110001010101000010110
i = 24:                          0010001111111011001000000101100010101010
i = 32:                                  00100011111110110010000001011000
i = 40:                                          001000111111101100100000
i = 48:                                                  0010001111111011
i = 56:                                                          00100011
Run Code Online (Sandbox Code Playgroud)

通过usig & 0xFF,我选择这个数字的最后8位.例:

x >> 48:           001000111111101100100000
0xff:                              11111111
(x >> 48) & 0xff:  000000000000000000100000
Run Code Online (Sandbox Code Playgroud)

由于前导零无关紧要,因此您可以获得所需的数字.

结果将转换为列表并以正常和反向顺序打印(就像OP想要的那样).

性能

我将此结果的时间与此线程中提出的其他解决方案进行了比较:

In: timeit list(reversed([(x >> i) & 0xFF for i in range(0,64,8)]))
100000 loops, best of 3: 13.9 µs per loop

In: timeit [(x >> (i * 8)) & 0xFF for i in range(7, -1, -1)]
100000 loops, best of 3: 11.1 µs per loop

In: timeit [(x >> i) & 0xFF for i in range(63,-1,-8)]
100000 loops, best of 3: 10.2 µs per loop

In: timeit reversed(struct.unpack('8B', struct.pack('Q', x)))
100000 loops, best of 3: 3.22 µs per loop

In: timeit reversed(struct.pack('Q', x))
100000 loops, best of 3: 2.07 µs per loop
Run Code Online (Sandbox Code Playgroud)

结果:我的解决方案不是最快的!目前,struct直接使用(由Mark Ransom提出)似乎是最快的片段.


Mar*_*som 7

在Python 2.x中,struct.pack返回一个字节字符串.将它转换为整数数组很容易.

>>> bytestr = struct.pack('>Q', 2592701575664680400)
>>> bytestr
'#\xfb X\xaa\x16\xbd\xd0'
>>> [ord(b) for b in bytestr]
[35, 251, 32, 88, 170, 22, 189, 208]
Run Code Online (Sandbox Code Playgroud)

structpython中的模块用于从python对象转换为字节字符串,通常根据C结构打包规则进行打包.struct.pack采用格式说明符(描述结构字节应如何布局的字符串)和一些python数据,并将其打包成字节字符串.struct.unpack反过来,采用格式说明符和字节字符串,并以python对象的格式再次返回解压缩数据的元组.

使用的格式说明符有两部分.前导字符指定字符串的字节顺序(字节顺序).以下字符指定要打包或解压缩的结构的字段类型.因此'>Q'意味着将给定数据打包为big-endian unsigned long long.要以相反的顺序获取字节,您可以使用<little-endian.

最后一个操作是一个列表推导,它迭代字节字符串的字符,并使用ord内置函数来获取该字符的整数表示.

最后说明:Python实际上并没有整数大小的概念.在2.x中,有int限制为32位,并且long大小不限.在3.x中,这两者统一为一种.因此,即使这个操作保证给出只占用一个字节的整数,但是如果你在其他操作中使用它们,注意python会强制生成的整数保持这种状态.