如何将 int8 数组转换为二进制并提取 python 中的位

how to convert int8 array to binary and extract bits in python

我有一个带有 int8 值的巨大 numpy 二维数组,我想将它转换为二进制值,提取一个或多个位,并仅使用 numpy 或类似库中的方法(例如numpy.wherenp.bitwise_and)。

例如:

array1 = [4, 128]
array_bits = [[0, 0, 0, 0, 0, 1, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0]]
#or ...
array_bits = ['00000100', '10000000']
#Extracting bit number 3 :
array_res = [1, 0]

我不太确定你为什么不想使用循环(老实说,我想不出你会用什么方法没有循环),但是这是我能找到的。

假设一个 int8 的二维数组:

nums = numpy.array([[random.randrange(255) for _ in range(20)],
                    [random.randrange(255) for _ in range(20)]], dtype=numpy.int8)

# Produces
array([[  27, -111,   79, -116, -114,   59,  -12,  -44,  -65,   66,   89,
        -116,    0,   15,  -31,   55,   54, -115,  115,   57],
       [  72,  -57,  -20,  -88,  -94, -112,  -40,   55,   47,  120,  125,
        -101,  117,  -35,  -29,  -41,  -68,  -76,  -11,  -67]], dtype=int8)

您可以使用 numpy.ndarray.tostring 方法将其转换为字节数组:

>>> nums.tostring()
b'\x1b\x91O\x8c\x8e;\xf4\xd4\xbfBY\x8c\x00\x0f\xe176\x8ds9H\xc7\xec\xa8\xa2\x90\xd87/x}\x9bu\xdd\xe3\xd7\xbc\xb4\xf5\xbd'

然后您可以使用一些格式(和循环)将其转换为二进制字符串列表:

>>> bin_strs = [f'{b:08b}' for b in nums.tostring()]
# bin_strs
['00011011',
 '10010001',
 '01001111',
 '10001100',
 '10001110',
 '00111011',
 ...
 ]

然后从 that,你可以使用切片和 int-casting 来获得特定的位,尽管你必须向后索引,因为第 0 位在右端:

>>> third_bits = [int(s[-3]) for s in bin_strs]
[0,
 0,
 1,
 1,
 1,
 0,
 ...
 ]

虽然结果不是二维的,但你没有提到它很重要。

我们可以使用 np.unpackbits 来帮助解决这个问题。为了使这个功能起作用,我们需要先将数据转换为 np.uint8

>>> lst = [4, 128]
>>> arr = np.array(lst, dtype=np.uint8)
>>> bits = np.unpackbits(arr)
>>> bits
array([0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], dtype=uint8)

现在要访问“第 3 位”,我们将使用索引 5,因为一个字节中有 8 位,而您希望第 3 位到最后。然后使用步长8继续在同一位置获取下一个值的位。

>>> bits[5::8]
array([1, 0], dtype=uint8)