Как я представляю и работаю с N-битными векторами в Python?
в задании, над которым я сейчас работаю, нам нужно работать с битовыми векторами, но я очень не уверен, как это сделать в Python. Они должны быть от 4 бит до 20 бит. Я никогда раньше не работал с битовым вектором, но я думаю, что можно было бы создать массивы неподписанных байтов, которыми вы управляли, используя обычные операции AND/OR/XOR.
на важное ограничение здесь: я не могу положиться на любой библиотеки, отличные от поставляемых со стандартным Python.
Я думаю, что знаю, как я бы это сделал в C, используя массивы 8 бит беззнаковых байтов: например, чтобы превратить 18-й бит нулевого массива в единицу, я бы сделал что-то вроде my_bit_array[3] &= 1
но, поскольку Python-это динамически типизированный и не имеют встроенный тип массива, как бы я идти о делать это в подходящие для Python способ?
и возможно ли это (как?) выразить битовый вектор размером 20? Я думаю возможно сделать 24 бит / 3 байтовый вектор и игнорирование 4 бит.
7 ответов
библиотека BitVector является библиотекой pure-Python для этой цели и должен соответствовать указанным вами потребностям.
Я удивлен, что никто не упомянул int
s (или я думаю long
в Python 2). int
s может быть сколь угодно большим, вы можете использовать побитовые операторы на них, они быстры, и код выглядит как битный код в 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.
я использовал это для bitvectors сотни бит длиной.
существует также pure-Python python-bitstring (С поддержкой Python 3).
немного устарел, но я собираюсь оставить еще один вариант 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