This is the python version of the same C++ question.
Given a number, num
, what is the fastest way to strip off the trailing zeros from its binary representation?
For example, let num = 232
. We have bin(num)
equal to 0b11101000
and we would like to strip the trailing zeros, which would produce 0b11101
. This can be done via string manipulation, but it'd probably be faster via bit manipulation. So far, I have thought of something using num & -num
Assuming num != 0
, num & -num
produces the binary 0b1<trailing zeros>
. For example,
num 0b11101000
-num 0b00011000
& 0b1000
If we have a dict
having powers of two as keys and the powers as values, we could use that to know by how much to right bit shift num
in order to strip just the trailing zeros:
# 0b1 0b10 0b100 0b1000
POW2s = { 1: 0, 2: 1, 4: 2, 8: 3, ... }
def stripTrailingZeros(num):
pow2 = num & -num
pow_ = POW2s[pow2] # equivalent to math.log2(pow2), but hopefully faster
return num >> pow_
The use of dictionary POW2s
trades space for speed - the alternative is to use math.log2(pow2)
.
Is there a faster way?
Perhaps another useful tidbit is num ^ (num - 1)
which produces 0b1!<trailing zeros>
where !<trailing zeros>
means take the trailing zeros and flip them into ones. For example,
num 0b11101000
num-1 0b11100111
^ 0b1111
Yet another alternative is to use a while loop
def stripTrailingZeros_iterative(num):
while num & 0b1 == 0: # equivalent to `num % 2 == 0`
num >>= 1
return num
Ultimately, I need to execute this function on a big list of numbers. Once I do that, I want the maximum. So if I have [64, 38, 22, 20]
to begin with, I would have [1, 19, 11, 5]
after performing the stripping. Then I would want the maximum of that, which is 19
.