Position of least significant bit that is set

后端 未结 23 1270
时光取名叫无心
时光取名叫无心 2020-11-22 08:46

I am looking for an efficient way to determine the position of the least significant bit that is set in an integer, e.g. for 0x0FF0 it would be 4.

A trivial impleme

23条回答
  •  谎友^
    谎友^ (楼主)
    2020-11-22 09:01

    Found this clever trick using 'magic masks' in "The art of programming, part 4", which does it in O(log(n)) time for n-bit number. [with log(n) extra space]. Typical solutions checking for the set bit is either O(n) or need O(n) extra space for a look up table, so this is a good compromise.

    Magic masks:

    m0 = (...............01010101)  
    m1 = (...............00110011)
    m2 = (...............00001111)  
    m3 = (.......0000000011111111)
    ....
    

    Key idea: No of trailing zeros in x = 1 * [(x & m0) = 0] + 2 * [(x & m1) = 0] + 4 * [(x & m2) = 0] + ...

    int lastSetBitPos(const uint64_t x) {
        if (x == 0)  return -1;
    
        //For 64 bit number, log2(64)-1, ie; 5 masks needed
        int steps = log2(sizeof(x) * 8); assert(steps == 6);
        //magic masks
        uint64_t m[] = { 0x5555555555555555, //     .... 010101
                         0x3333333333333333, //     .....110011
                         0x0f0f0f0f0f0f0f0f, //     ...00001111
                         0x00ff00ff00ff00ff, //0000000011111111 
                         0x0000ffff0000ffff, 
                         0x00000000ffffffff };
    
        //Firstly extract only the last set bit
        uint64_t y = x & -x;
    
        int trailZeros = 0, i = 0 , factor = 0;
        while (i < steps) {
            factor = ((y & m[i]) == 0 ) ? 1 : 0;
            trailZeros += factor * pow(2,i);
            ++i;
        }
        return (trailZeros+1);
    }
    

提交回复
热议问题