A,B和C是某些无符号整数类型的变量。从概念上讲,A是测试 vector ,B是“必需”位的位掩码(必须设置A中的至少一个对应位),C是“禁止”位的位掩码(不能设置A中的相应位)。由于我们混合了按位运算符和逻辑运算符,因此

A & B & ~C

是不正确的。标题表达等效于伪代码
((a0 & b0) | ... | (an & bn)) & (~(a0 & c0) & ... & ~(an & cn))

其中a0等表示各个位(而n是最高位的索引)。我看不到如何有效地重新排列此代码并取出相应的代码,但是,是否有一种聪明的方法(也许使用^)来简化标题中的表达式?

编辑:由@huseyintugrulbuyukisik的问题提示,我注意到我们可以假定(B & C) == 0,但我不知道这是否有帮助。

编辑2:结果:这取决于分支预测的良好程度!
#include <chrono>
#include <cmath>
#include <iostream>
#include <vector>

using UINT = unsigned int;
int main(void)
{
    const auto one = UINT(1);
    const UINT B = (one << 9); // Version 1
//  const UINT B = (one << 31) - 1;  // Version 2
    const UINT C = (one << 5) | (one << 15) | (one << 25);

    const size_t N = 1024 * 1024;
    std::vector<UINT> vecA(N);
    for (size_t i = 0; i < N; ++i)
        vecA[i] = (UINT)rand();

    int ct = 0; //To avoid compiler optimizations
    auto tstart = std::chrono::steady_clock::now();
    for (size_t i = 0; i < N; ++i)
    {
        const UINT A = vecA[i];
        if ((A & B) && !(A & C))
            ++ct;
    }
    auto tend = std::chrono::steady_clock::now();
    auto tdur = std::chrono::duration_cast<std::chrono::milliseconds>(tend - tstart).count();
    std::cout << ct << ", " << tdur << "ms" << std::endl;

    ct = 0;
    tstart = std::chrono::steady_clock::now();
    for (size_t i = 0; i < N; ++i)
    {
        const UINT A = vecA[i];
        if (!((!(A & B)) | (A & C)))
            ++ct;
    }
    tend = std::chrono::steady_clock::now();
    tdur = std::chrono::duration_cast<std::chrono::milliseconds>(tend - tstart).count();
    std::cout << ct << ", " << tdur << "ms" << std::endl;

    return 0;
}

版本1:
$ ./ops_test
    65578, 8ms
    65578, 3ms

版本2:
$ ./ops_test
    130967, 4ms
    130967, 4ms

这些是代表值(实际上,我多次运行每个测试)。 g++ 4.8.4,默认优化。我在B中仅设置了4位,得到了类似版本2的结果。但是,我的用例仍然接近版本1,因此我认为@DougCurrie的答案是一种改进。

最佳答案

!(A & B)必须为零
A & C必须为零

所以
(!(A & B)) | (A & C)必须为零

这将保存与&&关联的分支;一些编译器也可以将!优化为无分支。

09-05 01:14