18

在我目前正在处理的一项作业中,我们需要使用位向量,但我非常不确定如何在 Python 中执行此操作。它们应该能够从 4 位到 20 位。我以前从未使用过位向量,但我想有人会创建您使用通常的 AND/OR/XOR 操作操作的无符号字节数组。

这里的重要限制是:除了标准 Python 提供的库之外,我不能依赖任何库。

我想我知道如何在 C 中使用 8 位无符号字节的数组来执行此操作:例如,要将零数组的第 18 位变为 1,我会执行类似 my_bit_array[3] &= 1<<2

但是由于 Python 是动态类型的并且没有内置的数组类型,我将如何以 Python 的方式执行此操作?

是否有可能(如何?)表达一个大小为 20 的位向量?我正在考虑制作一个 24 位/3 字节向量并忽略 4 位。

4

7 回答 7

34

我很惊讶没有人提到ints (或者我猜long在 Python 2 中)。 ints 可以任意大,您可以对它们使用按位运算符,它们速度很快,并且代码看起来像 C 中的位旋转代码(我认为这是一个优势)。

x = 0 # empty
x |= 1<<19 # set bit 19
x &= ~(1<<19) # clear bit 19
x ^= 1<<19 # toggle bit 19
x = ~x # invert *all* bits, all the way to infinity
mask = ((1<<20)-1) # define a 20 bit wide mask
x &= mask # ensure bits 20 and higher are 0
x ^= mask # invert only bits 0 through 19

(x >> 19) & 1 # test bit 19
(x >> 16) & 0xf # get bits 16 through 20.

我已经将它用于数百位长的位向量。

于 2017-04-17T20:15:34.250 回答
10

BitVector是用于此目的的纯 Python 库,应该满足您指定的需求。

于 2010-01-27T15:01:19.403 回答
9

它有列表,你可以用布尔值填充:

[False] * 20
于 2010-01-27T15:00:49.297 回答
9

bitarray模块使用布尔值有效地做到了这一点

于 2010-01-27T15:02:15.003 回答
3

使用结构模块。

于 2010-01-27T15:00:52.230 回答
2

有点过时了,但为了比较起见,我将在此处留下另一个 stdlib 选项。使用ctypes模块也很容易做到这一点。

例如:

是否有可能(如何?)表达大小为 20 的位向量?我正在考虑制作一个 24 位/3 字节向量并忽略 4 位。

class Simple(ctypes.LittleEndianStructure):
    _pack_ = 1
    _fields_ = [
                 ('one', ctypes.c_ubyte, 8),
                 ('two', ctypes.c_ubyte, 8),
                 ('three', ctypes.c_ubyte, 8)
               ]

s = Simple(0, 2, 256)
bytearray(s)        # bytearray(b'\x00\x02\x00')
s = Simple(0, 2, 255)
bytearray(s)        # bytearray(b'\x00\x02\xff')

class Simple(ctypes.BigEndianStructure):
    _pack_ = 1
    _fields_ = [
                 ('one', ctypes.c_ubyte, 8),
                 ('two', ctypes.c_ubyte, 8),
                 ('three', ctypes.c_ubyte, 8)
               ]

s = Simple(0, 2, 256)
bytearray(s)        # bytearray(b'\x00\x02\x00')
s = Simple(0, 2, 255)
bytearray(s)        # bytearray(b'\x00\x02\xff')

s.two |= 3
bytearray(s)        # bytearray(b'\x00\x03\xff')

或者像这样更直接的东西:

class bit_vector(Structure):
    _fields_ = [('bits', c_uint32, 24),
                ('unused', c_uint32, 8),
                ]

bv = bit_vector()
# turn on the 18th bit -- being explicit just to demo it
bv.bits |= int('000000000000000001000000', 2)
bin(bv.bits)   # 0b1000000
于 2016-11-01T17:06:16.920 回答
1

还有纯 Python python-bitstring(支持 Python 3)。

于 2012-10-12T12:20:37.363 回答