繁体   English   中英

Python/Numpy - 提取字节数

[英]Python/Numpy - Extracting Bits of Bytes

我有numpy.frombuffer()数组形式的 8 个字节的数据。 我需要将第 10-19 位放入变量,将第 20-29 位放入变量。 如何使用 Python 提取跨字节的位? 我读过关于位移的文章,但我不清楚这是否是这样做的方法。

通过索引正确的字节来单独获取每个位,然后屏蔽正确的位。 然后,您可以移位和添加以从位构建新数字。

data = b'abcdefgh' #8 bytes of data

def bit_slice(data, start, stop):
    out = 0
    for i in range(start, stop):
        byte_n = i//8
        byte_bit = i%8
        byte_mask = 1<<byte_bit
        bit = bool(data[byte_n] & byte_mask)
        out = out*2 + bit #multiply by 2 is equivalent to shift. Then add the new bit
    return out

回复:评论

每次我们想为我们的数字添加一个新位时,如下所示:

10110
101101

我们必须将前五位移位,然后根据下一位的值加 1 或 0。 向左移动每个数字高一位,这在二进制中意味着乘以 2。在十进制中,将一个数字移一位意味着乘以 10。当将新位添加到我们的数字时,我们正在累加我只是乘以 2使用右移运算符只是为了表明它是另一种选择。 创建字节掩码时,我确实使用了右移运算符 ( << )。 它的工作原理是将 1 移动几个位置,所以我最终得到一个在正确位置有一个 1 的字节,当我用有问题的字节“和”它时,我只得到我想要索引的单个位:

1<<3 = 00001000
1<<5 = 00100000
1<<0 = 00000001
1<<7 = 10000000

然后应用掩码以获得我们想要的位:

10011011 #一个字节的数据
00100000 #bit 掩码为 32 位
_________&
00 0 00000
#bit 在 32 的位置是 0

10011011 #一个字节的数据
00010000 #bit 掩码为 16 位
_________&
000 1 0000
#bit 在 16 的位置是 1

应用掩码后,如果所选位为 0,则整个数字将始终为 0。如果所选位为 1,则数字将始终大于 0。对该结果调用bool等效于:

if data[byte_n] & byte_mask > 0:
    bit = 1
else:
    bit = 0

... 因为解释为整数的布尔值只是一个 1 或一个 0。

根据您的数据类型,您可能需要稍微修改这个 numpy 解决方案:

a = np.frombuffer(b'\x01\x02\x03\x04\x05\x06\x07\x08', dtype=np.uint8)
#array([1, 2, 3, 4, 5, 6, 7, 8], dtype=uint8)

拆包位:

first = np.unpackbits(a)[10:20]
#array([0, 0, 0, 0, 1, 0, 0, 0, 0, 0], dtype=uint8)

如果您需要重新打包这些位:

first_packed = np.packbits(first)
array([8, 0], dtype=uint8)

请注意,python 是基于 0 的索引,如果您想要第np.unpackbits(a)[9:19]元素,请将上述索引调整为np.unpackbits(a)[9:19]

其他情况类似:

second = np.unpackbits(a)[20:30]
#array([0, 0, 1, 1, 0, 0, 0, 0, 0, 1], dtype=uint8)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM