How to find out the position of the nth 1 of a binary number most efficiently?

for example, the integer 430 (110101110 in binary), I want to find out where the fourth 1 of this number starts on the right, which in this case is 5 (the ordinal starts at 0).

are there any efficient algorithms? The implementation of any language is fine.


it will be very easy to start from the right. If I start from the left, I won't write the code. I'll just talk about the train of thought. It's very simple.

first do the operation with 110101110 and 100000000. If the leftmost one is 1, you will know.

then move 110101110 one bit to the left to 101011100, and then do the & operation with 100000000, and just count yourself.

time complexity O (n), this complexity can not escape, but only the optimization of writing, the best way to write is undoubtedly bit operation.

< hr >

if you start from the right, it's even easier. The method is the same as above, but the number of the & operation with 110101110 is changed to 1, and then each time the direction of movement changes to the right, but note that the right shift divides the logical right shift and the arithmetic right shift, and needs to make a transformation. For more information, please see https://subetter.com/articles.

.

JS

var str = change(430); //
console.log(str);
var num = 0;
for (var i = 0; i < str.length; iPP) {
    //1num1
    if (str[i] == 1) {
        num += 1;
        //num4i
        if (num == 4) {
            console.log(i);
        }
    }
}

function change(number) {
    var temparr = []; //
    var temp; //
    var temostr = '';
    //
    while (number > 0) {
        //2temp
        temp = number % 2;
        //01push
        temparr.push(temp);
        //22
        number = Math.floor(number / 2);
        //0
    }
    while (temparr.length != 0) {
        //
        temostr += temparr.pop().toString();
    }
    return temostr; //
}

JS

//  110101110   430
// 
/^(.*?)((10*){4})$/g.exec((430).toString(2))[2].length - 1
// 
/^(.*?)((10*){4})$/g.exec((430).toString(2))[1].length - 1

it is most efficient to use assembly instructions. Here we use python to simulate the algorithm.

python3

-sharpn1

-sharp popcnt cpu
def popcnt(b):
    n=0
    while(b):
        n+=1
        b &= b-1
    return n

def x(b, n):
    for i in range(n-1):
        b &= b-1
    return popcnt(b ^ (b-1))
    
b = 0b110101110
n = 4
print(x(b, n))
-sharp 6 -sharp-sharp 1 6
Menu