在C中查找位掩码中的设置位位置的最佳方法

这个问题在这里已经有了答案:

  • 如何计算一个32位整数中的设置位数? 50个答案

  • 来自Hacker's Delight的算法(书):

    int count_bits(long long s)
    {
        s = (s&0x5555555555555555L) + ((s>>1)&0x5555555555555555L);
        s = (s&0x3333333333333333L) + ((s>>2)&0x3333333333333333L);
        s = (s&0x0F0F0F0F0F0F0F0FL) + ((s>>4)&0x0F0F0F0F0F0F0F0FL);
        s = (s&0x00FF00FF00FF00FFL) + ((s>>8)&0x00FF00FF00FF00FFL);
        s = (s&0x0000FFFF0000FFFFL) + ((s>>16)&0x0000FFFF0000FFFFL);
        s = (s&0x00000000FFFFFFFFL) + ((s>>32)&0x00000000FFFFFFFFL);
    
        return (int)s;
    }
    

    除了已经解释过的好点儿,还有其他选择。

    这假设你有x86(64),SSE4,gcc并且可以使用-msse4开关编译,你可以使用:

    int CountOnesSSE4(unsigned int x)
    {
        return __builtin_popcount(x);
    }
    

    这将编译成单一的popcnt指令。 如果你需要快速代码,你可以在运行时检查SSE,并使用最好的功能。

    如果你希望数字的数量少一些,这可能也很快(并且总是比通常的移位和比较循环更快):

    int CountOnes(unsigned int x)
    {
        int cnt = 0;
        while (x) {
            x >>= ffs(x);
            cnt++;
        }
        return cnt;
    }
    

    在x86上(即使没有SSE),ffs将编译成单指令(bsf),并且循环的数目将取决于数目。


    你可能会这样做:

    long long bit_mask = 0xdeadbeefdeadbeef;
    
    int i;
    for (i = 0; i < (sizeof(long long) * 8); i++) {
        int res = bit_mask & 1;
        printf ("Pos %i is %in", i, res);
        bit_mask >>= 1;
    
    }
    
    链接地址: http://www.djcxy.com/p/72599.html

    上一篇: Best method to find out set bit positions in a bit mask in C

    下一篇: C++ how to get length of bits of a variable?