Побитовые операции для изменения 2 LSB

Предположим, у меня есть список чисел:

l = [30, 31, 32, 33]

В двоичном виде это будет так же, как

l = [00011110, 00011111, 00100000, 00100001]

Используя бинарные операции, я хочу установить наименее 2 значащих бита в любое случайное значение, но сохранить 6 старших значащих битов. Примером этого может быть:

l_new = [00011111, 00011101, 00100010, 00100010]

Как я могу это сделать, используя библиотеку numpy в python?


person Mike    schedule 03.04.2017    source источник
comment
Это можно сделать достаточно легко без NumPy.   -  person Ignacio Vazquez-Abrams    schedule 03.04.2017


Ответы (2)


Вы можете использовать numpy.unpackbits

l = np.random.randint(16,size=(10,)).astype(np.uint8)
# [ 9 13  3 10 10]

bits = np.unpackbits(l[:,np.newaxis],axis=1)
# [[0 0 0 0 1 0 0 1]
#  [0 0 0 0 1 1 0 1]
#  [0 0 0 0 0 0 1 1]
#  [0 0 0 0 1 0 1 0]
#  [0 0 0 0 1 0 1 0]]

bits[:,-2:] = np.random.randint(0,2,size=(bits.shape[0],2))
# [[0 0 0 0 1 0 0 1]
#  [0 0 0 0 1 1 0 1]
#  [0 0 0 0 0 0 1 0]
#  [0 0 0 0 1 0 0 1]
#  [0 0 0 0 1 0 0 1]]

np.squeeze(np.packbits(bits,axis=1))
# [ 9 13  2  9  9]
person Crispin    schedule 03.04.2017

Вы можете использовать побитовый xor:

a = np.random.randint(0, 256, (10,))
b = np.random.randint(0, 4, a.shape)
a
# array([131,  79, 186,  90, 102, 179, 247,  28,  58,  60])
b
# array([2, 0, 2, 1, 0, 0, 2, 0, 3, 3])
a^b
# array([129,  79, 184,  91, 102, 179, 245,  28,  57,  63])

Продемонстрируйте правильность:

a = np.random.randint(0, 256, (10,))
b = np.random.randint(0, 4, (1000000,) + a.shape)

# show it leaves high 6 unchanged:
print(np.all(252&a == 252&(a^b)))
# show all low 2 values equally likely:
print(np.abs(np.array([np.histogram(c, np.arange(5)-0.5, normed=True)[0] for c in ((a^b)&3).T])-0.25).max())

# True
# 0.001595
person Paul Panzer    schedule 03.04.2017