问题
I am working with Bitmasks
in python
. As far as I know, these are arrays of integers that when they are unpacked into binary format they tell you which of the 32 bits are set (=1) for a given element in the array.
I would like to know the fastest way to check whether 4 specific bits are set or not for any element of an array. I do not care about the rest. I have tried the following solution but it is not fast enough for my purpose:
def detect(bitmask, check=(18,22,23,24), bits=32):
boolmask = np.zeros(len(bitmask), dtype=bool)
for i, val in enumerate(bitmask):
bithost = np.zeros(bits, dtype='i1')
masklist = list(bin(val)[2:])
bithost[:len(masklist)] = np.flip(masklist,axis=0)
if len(np.intersect1d(np.nonzero(bithost)[0] ,check)) != 0:
boolmask[i] = True
else:
boolmask[i] = False
if any(boolmask):
print("There are some problems")
else:
print("It is clean")
For example, if a given bitmask
contains the integer 24453656 (1011101010010001000011000 in binary)
, the output of function detect would be "There are some problems" since bit 22 is set:
bit: ... 20, 21, 22, 23, 24,...
mask: ... 0, 0, 1, 0, 0,...
Any ideas on how to improve the performance?
回答1:
Integers are nothing but sequence of bits in the computer.
So, if you get integer, let's say: 333 it is a sequence of bits 101001101 to the computer. It doesn't need any unpacking into bits. It is bits.
Therefore, if the mask is also an integer, you don't need any unpacking, just apply bitwise operations to it. Check wikipedia for details of how these work.
In order to check if ANY of the bits xyz are set in an integer abc, you do:
(abc & xyz) > 0
. If you absolutely need checking mask to be a tuple of bit places, you do some packing, like this:
def detect(bitmask,check=(18,22,23,24)):
checkmask=sum(2**x for x in check)
if (bitmask & checkmask) > 0:
print "There are some problems"
else:
print "Everything OK"
Note that bitmasks start with 0 based bit indices. First bit is bit 0.
回答2:
I am not sure what's in your bitmask
argument. Regarless, you should probably use bitwise operators.
Make a bit mask like this:
def turn_bits_on(bits):
n = 0
for k in bits:
n = (n | (1 << (k - 1))) if k > 0 else n
return n
bits_to_check = turn_bits_on([18, 22, 23, 24])
Then, for a single number, you can detect with:
def is_ok(value, mask):
return not (value & mask)
print(is_ok(24453656, bits_to_check))
Finally, depending on what your bitmask
value is (a list, a DataFrame, etc), apply the is_ok()
function to each value.
Hope this helps!
来源:https://stackoverflow.com/questions/53724160/checking-specific-bits-of-a-bitmask