Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 计算位或查找最右|最左位的高效按位操作_C++_C_Binary_Bit Manipulation_Bits - Fatal编程技术网

C++ 计算位或查找最右|最左位的高效按位操作

C++ 计算位或查找最右|最左位的高效按位操作,c++,c,binary,bit-manipulation,bits,C++,C,Binary,Bit Manipulation,Bits,给定一个无符号int,我必须实现以下操作: 计算设置为1的位数 查找最左边1位的索引 查找最右边1位的索引 (操作不应与体系结构相关) 我已经使用逐位移位完成了这项工作,但是我必须迭代几乎所有的位(es.32)。 例如,计算1: unsigned int number= ...; while(number != 0){ if ((number & 0x01) != 0) ++count; number >>=1; } 其他操作与此类似 所以我

给定一个无符号int,我必须实现以下操作:

  • 计算设置为1的位数
  • 查找最左边1位的索引
  • 查找最右边1位的索引
  • (操作不应与体系结构相关)

    我已经使用逐位移位完成了这项工作,但是我必须迭代几乎所有的位(es.32)。 例如,计算1:

    unsigned int number= ...;
    while(number != 0){
        if ((number & 0x01) != 0)
            ++count;
        number >>=1;
    }
    
    其他操作与此类似

    所以我的问题是:有没有更快的方法可以做到这一点?

    看看ffs(3)、ffsl(3)、fls(3)、flsl(3)

    ffs()和ffsl()函数查找i中的第一个位集(从最低有效位开始),并返回该位的索引

    fls()和flsl()函数查找i中设置的最后一位,并返回该位的索引

    您可能也对位字符串(3)感兴趣。

    如果您想要最快的方法,您将需要使用不可移植的方法

    Windows/MSVC:

    GCC:

    这些指令通常直接映射到本机硬件指令。所以它不会比这些更快

    但由于没有C/C++功能,它们只能通过编译器内部函数访问

    对32位整数v中的位进行计数的最佳方法如下:

    unsigned int v; // count bits set in this (32-bit value)
    unsigned int c; // store the total here
    v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
    c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
    
    最佳位计数方法只需要12次操作,这与查找表方法相同,但避免了表的内存和潜在缓存未命中。它是上述纯并行方法和早期使用乘法的方法(在使用64位指令计算位的部分中)的混合,尽管它不使用64位指令。字节中设置的位的计数并行进行,字节中设置的位的总和通过乘以0x1010101并右移24位来计算

    数字x的“最右1位”由以下公式给出

    pos(1st '1') = log_2(x XOR (x-1) + 1) - 1
    
    例如:

    最后一行的base2日志将为您提供正确的位置+1。因此,从日志结果中减去1,您将得到最正确的“1”位

    对于最右边的“0”位,可以使用

    pos(1st '0') = log_2(x XOR (x+1) + 1) - 1
    

    对于最右边的位简单ans

    第一种方法

    }

    第二种方法


    }

    考虑获取一份《黑客之乐》,里面充满了对此类低级操作的讨论。另外:感谢链接。非常有趣。如果只设置了一些位,则效率非常高。这不是平台独立的。
    pos(1st '0') = log_2(x XOR (x+1) + 1) - 1
    
    unsigned int getFirstSetBit(int n){
    
    return log2(n & -n) + 1; 
    
    unsigned int getFirstSetBit(int n){
    
    return ffs(n);