如何在 python 中利用字节数组的每一位
How to utilize every bit of a bytearray in python
我有这样一个字节数组:
a=bytearray([False]*size)
我不想将 False
值存储为字节,而是字节数组中的一个位;我关心的是记忆。无论如何我可以做到吗?因为使用 8 位来存储 1 位值似乎是一种浪费。我也不能使用位数组导入。我现在已经花了几个小时在这上面,所以任何帮助将不胜感激。
这是一个简单的 class,可以满足您的需求。它在 bytearray
类型之上实现位数组:
class BitArray:
def __init__(self, size):
self.size = size
self.bytearray = bytearray((size + 7) >> 3)
def clear(self):
ba = self.bytearray
for i in range(len(ba)):
ba[i] = 0
def get_bit(self, bit_ix):
if not isinstance(bit_ix, int):
raise IndexError("bit array index not an int")
if bit_ix < 0 or bit_ix >= self.size:
raise IndexError("bit array index out of range")
byte_ix = bit_ix >> 3
bit_ix = bit_ix & 7
return (self.bytearray[byte_ix] >> bit_ix) & 1
def set_bit(self, bit_ix, val):
if not isinstance(bit_ix, int):
raise IndexError("bit array index not an int")
if bit_ix < 0 or bit_ix >= self.size:
raise IndexError("bit array index out of range")
if not isinstance(val, int):
raise ValueError("bit array value not an int")
if val not in (0, 1):
raise ValueError("bit array value must be 0 or 1")
byte_ix = bit_ix >> 3
bit_ix = bit_ix & 7
bit_val = 1 << bit_ix
if val:
self.bytearray[byte_ix] |= bit_val
else:
self.bytearray[byte_ix] &= ~bit_val
def __getitem__(self, key):
return self.get_bit(key)
def __setitem__(self, key, value):
self.set_bit(key, value)
位数组在创建时最初全为零。 clear
方法将所有位设置为零,get_bit
方法将return一个位的值,set_bit
方法将一个位的值设置。所有位值都是 0
或 1
(尽管您可以轻松地将其更改为 True
或 False
)。
这是一个如何使用它的例子:
ba = BitArray(23)
print(ba.get_bit(17))
ba.set_bit(17, 1)
print(ba.get_bit(17))
ba.clear()
print(ba.get_bit(17))
这将创建一个足以容纳 23 位的位数组。然后打印第 17 位,即 0。然后将第 17 位设置为 1 并打印它。然后它清除整个数组并再次打印第 17 位。输出为:
0
1
0
更新:我添加了 __getitem__
和 __setitem__
,因此您现在可以使用索引符号直接索引各个位。示例:
ba[17] = 1
print(ba[17])
这会将第 17 位设置为 1,然后打印它。输出为:
1
注意索引必须是整数。不支持切片。
我有这样一个字节数组:
a=bytearray([False]*size)
我不想将 False
值存储为字节,而是字节数组中的一个位;我关心的是记忆。无论如何我可以做到吗?因为使用 8 位来存储 1 位值似乎是一种浪费。我也不能使用位数组导入。我现在已经花了几个小时在这上面,所以任何帮助将不胜感激。
这是一个简单的 class,可以满足您的需求。它在 bytearray
类型之上实现位数组:
class BitArray:
def __init__(self, size):
self.size = size
self.bytearray = bytearray((size + 7) >> 3)
def clear(self):
ba = self.bytearray
for i in range(len(ba)):
ba[i] = 0
def get_bit(self, bit_ix):
if not isinstance(bit_ix, int):
raise IndexError("bit array index not an int")
if bit_ix < 0 or bit_ix >= self.size:
raise IndexError("bit array index out of range")
byte_ix = bit_ix >> 3
bit_ix = bit_ix & 7
return (self.bytearray[byte_ix] >> bit_ix) & 1
def set_bit(self, bit_ix, val):
if not isinstance(bit_ix, int):
raise IndexError("bit array index not an int")
if bit_ix < 0 or bit_ix >= self.size:
raise IndexError("bit array index out of range")
if not isinstance(val, int):
raise ValueError("bit array value not an int")
if val not in (0, 1):
raise ValueError("bit array value must be 0 or 1")
byte_ix = bit_ix >> 3
bit_ix = bit_ix & 7
bit_val = 1 << bit_ix
if val:
self.bytearray[byte_ix] |= bit_val
else:
self.bytearray[byte_ix] &= ~bit_val
def __getitem__(self, key):
return self.get_bit(key)
def __setitem__(self, key, value):
self.set_bit(key, value)
位数组在创建时最初全为零。 clear
方法将所有位设置为零,get_bit
方法将return一个位的值,set_bit
方法将一个位的值设置。所有位值都是 0
或 1
(尽管您可以轻松地将其更改为 True
或 False
)。
这是一个如何使用它的例子:
ba = BitArray(23)
print(ba.get_bit(17))
ba.set_bit(17, 1)
print(ba.get_bit(17))
ba.clear()
print(ba.get_bit(17))
这将创建一个足以容纳 23 位的位数组。然后打印第 17 位,即 0。然后将第 17 位设置为 1 并打印它。然后它清除整个数组并再次打印第 17 位。输出为:
0
1
0
更新:我添加了 __getitem__
和 __setitem__
,因此您现在可以使用索引符号直接索引各个位。示例:
ba[17] = 1
print(ba[17])
这会将第 17 位设置为 1,然后打印它。输出为:
1
注意索引必须是整数。不支持切片。