как преобразовать массив int8 в двоичный файл и извлечь биты в Python - PullRequest
0 голосов
/ 31 октября 2019

У меня есть огромный двумерный массив с значениями int8, и я хотел бы преобразовать его в двоичные значения, извлекая один или несколько битов, и создать новый массив без циклов, используя только методы из numpy или таких библиотек, как этот (например, numpy.where или np.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]

Ответы [ 2 ]

0 голосов
/ 01 ноября 2019

Мы можем использовать 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)

Теперь, чтобы получить доступ к «третьему» биту, мы будем использовать индекс 5, так как в байте 8 бит, а выхочу 3-го до последнего. Затем используйте шаг 8, чтобы продолжить получать бит следующего значения в той же позиции.

>>> bits[5::8]
array([1, 0], dtype=uint8)
0 голосов
/ 31 октября 2019

Я не совсем уверен, почему вы не хотите использовать циклы (и, честно говоря, я не могу придумать, как бы вы это сделали без циклов), но вот что я смогfind.

Предполагая, что 2D-массив int8s:

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',
 ...
 ]

, затем из , что , вы можете использовать нарезку иint-приведение для получения определенных битов, хотя вам придется индексировать в обратном направлении, поскольку 0-й бит находится на правом конце:

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

Конечно, результат не 2D, но вы не упомянули, чтокак важный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...