Reputation: 49
Suppose I have an list of numbers:
l = [30, 31, 32, 33]
In binary this would the same as
l = [00011110, 00011111, 00100000, 00100001]
Using binary operations I want to set the least 2 significant bits to any random value, but retain the 6 most significant bits. An example of this might be:
l_new = [00011111, 00011101, 00100010, 00100010]
How can I do this, using the numpy library in python?
Upvotes: 1
Views: 316
Reputation: 53089
You can use bitwise 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])
Demonstrate correctness:
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
Upvotes: 1
Reputation: 2120
You can use 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]
Upvotes: 1