Тестирование на биты на numpy - PullRequest
0 голосов
/ 15 января 2020

Мне нужно выполнить синтаксический анализ битового потока, используя Python & numpy. Кажется, что это не так просто, как побитовое и, похоже, не работает с numpy байтами (uint8).

Что мне здесь не хватает ..?

import bitstring
import numpy

byteform = b"\x56"
bitarray = bitstring.BitArray(byteform)
numbyte = numpy.uint8(56)
pyint = 56

bitarray.bin
# that gives '01010110'
#                  ^^^
# I want to test for these bits

# this one is the only one that works:
byteform[0] & 1 # 0 => ok
byteform[0] & 2 # 2 => ok
byteform[0] & 4 # 4 => ok
# why do I need that [0] ?

# this does not work at all.. why?
numbyte & 1 # 0
numbyte & 2 # 0
numbyte & 4 # 0

# no luck with this one either:
numpy.bitwise_and(numbyte, numpy.uint8(1))
numpy.bitwise_and(numbyte, numpy.uint8(2))
numpy.bitwise_and(numbyte, numpy.uint8(4))

# this shouldnt give the expected results since the bits are in the other end of the bytearray (it's small endian):
pyint & 1
pyint & 2
pyint & 4

В numpy .uint8, есть какие-нибудь хитрые лишние биты? Помощь!

1 Ответ

1 голос
/ 15 января 2020

Байт-форма на самом деле не работает, и вы должны понимать, что это не работает, если вы сериализуете представление:

>>> print("{:08b}".format(56))
00111000

Итак, мы ожидаем, что будут установлены только младшие 3 бита и верхние 2 бита , Ваше значение не 56 в байтовой форме, это шестнадцатеричное значение 0x56, что составляет 86. Только 8, 16 и 32 должны быть действительными битами в вашем уравнении, и NumPy работает просто отлично.

>>> print(byteform[0])
86
>>> print(0x56)
86

Если вы хотите преобразовать число в двоичное, вы можете использовать numpy.tobytes или int.to_bytes.

>>> np.uint8(56).tobytes()
b'8'
>>> int.to_bytes(56, length=1, byteorder='little', signed=False)
b'8'

В нотации для определения байта '\ xNN' для этого не используются десятичные числа. NN, он использует шестнадцатеричные числа, поэтому 0xNN создает байт с числовым значением, эквивалентным 0xNN.

Предупреждение

С NumPy и большими числами, I на самом деле рекомендую делать только побитовые операции между NumPy целыми числами.

>>> SIGN_MASK = np.uint64(0x8000000000000000) 
>>> INFINITY_BITS = np.uint64(0x7FF0000000000000)                          
>>> SIGN_MASK | INFINITY_BITS                                              
18442240474082181120
>>> SIGN_MASK | int(INFINITY_BITS)
TypeError: ufunc 'bitwise_or' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

Это связано с тем, что для больших чисел NumPy не уверен, должно ли число быть подписанным или беззнаковым, и, следовательно, не может определить действительное побитовое представление.

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