如何在 Python 中表示和使用 n 位向量?

发布于 2024-08-19 12:24:19 字数 430 浏览 14 评论 0原文

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

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

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

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

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

In an assignment I am currently working on we need to work with bit vectors, but I am very unsure of how to do this in Python. They should be able to be from 4 bits to 20 bits. I have never worked with bit vector before, but I guess that one would one create arrays of unsigned bytes that you manipulated using the usual AND/OR/XOR operations.

The important restriction here is: I cannot rely on any libraries other than those supplied with standard Python.

I think I know how I would do this in C using arrays of 8 bit unsigned bytes:
e.g. to turn the 18th bit of a zeroed array into a one, I would do something like
my_bit_array[3] &= 1<<2

But since Python is dynamically typed and does not have a built-in array type, how would I go about doing this in a pythonic way?

And is it possible (how?) to express a bit vector of size 20? I am thinking of perhaps making a 24 bit / 3 byte vector and ignoring the 4 bits.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

公布 2024-08-26 12:24:19

我很惊讶没有人提到 int(或者我猜是 Python 2 中的 long)。 int 可以任意大,您可以对它们使用按位运算符,它们速度很快,并且代码看起来像 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.

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

I'm surprised that no one has mentioned ints (or I guess long in Python 2). ints can be arbitrarily large, you can use bitwise operators on them, they're fast, and the code looks like bit twiddling code in C (I consider that to be an advantage).

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.

I've used this for bitvectors hundreds of bits long.

筱武穆 2024-08-26 12:24:19

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

The library BitVector is a pure-Python library for this purpose, and should suit the needs you specified.

长不大的小祸害 2024-08-26 12:24:19

bitarray 模块可以使用布尔值有效地完成此操作。

The bitarray module does this efficiently with booleans.

摇划花蜜的午后 2024-08-26 12:24:19

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

[False] * 20

It has lists, which you can populate with bools:

[False] * 20
弥繁 2024-08-26 12:24:19

使用 struct 模块。

Use struct module.

伤痕我心 2024-08-26 12:24:19

有点过时,但我将在这里留下另一个 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

A bit dated but I'm going to leave another stdlib option here just for comparison sake. It is also easy to do this using the ctypes module.

For example:

And is it possible (how?) to express a bit vector of size 20 ?
I am thinking of perhaps making a 24 bit / 3 byte vector and ignoring the 4
bits.

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')

or something more straight forward like this:

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
流年里的时光 2024-08-26 12:24:19

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

There is also the pure-Python python-bitstring (with Python 3 support).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文