按位比较和计数位

时间:2016-04-27 17:27:49

标签: c++ bit-manipulation

我有一个非常具体的问题,我希望得到你的意见:

给定一个32位整数,我想知道有多少2位块小于或等于00,01或10.我知道2位-pattern我在编译时比较整数。

00 01 10 11 01 11 00 10 ... // 4 blocks <= 01

到目前为止,我使用if-constructs并创建一个应用于整数并调用__builtin_popcount()的位掩码。以下是有关如何在32位整数上检查word <= 01的示例。

__builtin_popcount(~(word | 0x55555555))

不幸的是,这些案例的区别(总共3个)花费了很多时间,我想加快速度。迭代整数并按块比较可能是一个更糟糕的想法。我有机会进一步提高吗?

3 个答案:

答案 0 :(得分:2)

将所有2位位掩码存储在一个数组中。 缓存32位整数。

对于32位整数的每个2位块:

将缓存的整数恢复为临时整数。

&LT;&LT;为了清除更重要的比特,然后比特移位&gt;&gt; 30位,使您想要检查的位是寄存器中的两个最低有效位。

对于每个掩码,按位AND。将结果缓存到先前分配的数组的某个子集。

循环,根据需要更改bitshift以获得不同的掩码。

在第一次迭代中,&lt;&lt; 30位,&gt;&gt; 30位。 在第二次迭代中,&lt;&lt; 28位,&gt;&gt; 30位。

答案 1 :(得分:1)

在运行时(理论上)计算此值的最快方法是预先计算结果。

警告,这可能需要一段时间才能编译......

Set

结果可能会有所不同:

#include <iostream>
#include <limits>
#include <utility>

constexpr int bits_less(unsigned int sample, int cmp)
{
    auto samples = std::numeric_limits<unsigned int>::digits;
    auto tot = 0;
    while (samples)
    {
        auto acc = sample & 0x3;
        if (acc <= cmp)
            ++tot;
        sample >>= 2;
        samples -= 2;
    }
    return tot;

}

struct less_table
{
    constexpr less_table()
    : less_table(std::make_index_sequence<entries>())
    {}

    template<std::size_t...Is>
    constexpr less_table(std::index_sequence<Is...>)
    : less_tab {
        { bits_less(Is, 0), bits_less(Is, 1), bits_less(Is, 2) }
    }
    {}

    constexpr int get(unsigned int sample, int pattern) const
    {
        return less_tab[sample][pattern];
    }

    static constexpr std::size_t entries = std::size_t(std::numeric_limits<unsigned int>::max()) + 1;
    int less_tab[entries][3];
};

int main()
{
    std::cout << bits_less(0x34237645, 0x01) << std::endl;

    constexpr less_table lt;
    std::cout << lt.get(0x34237645, 0x01) << std::endl;
}

享受:)

答案 2 :(得分:1)

通过适当的位操作,可以有效地处理这三种情况中的每一种:

#include <iostream> 

int main()
{
    unsigned int value{0xE4E79EEF};

    unsigned int A{~(value | 0x55555555)};
    unsigned int B{~((~value) | 0x55555555)};
    unsigned int C{(~(value | 0xAAAAAAAA)) << 1};
    unsigned int D{(~((~value) | 0xAAAAAAAA)) << 1};

    int lt00{16 - __builtin_popcount(B|D)};
    int lt01{__builtin_popcount(A)};
    int lt10{__builtin_popcount(A|C)};

    std::cout << "Original bit pattern: 11 10 01 00 11 10 01 11 10 01 11 10 11 10 11 11\n";
    std::cout << "Number of 2-bit blocks less than or equal to 00: " << lt00 << " block(s)\n";
    std::cout << "Number of 2-bit blocks less than or equal to 01: " << lt01 << " block(s)\n";
    std::cout << "Number of 2-bit blocks less than or equal to 10: " << lt10 << " block(s)\n";

    return 0;
}

产地:

Original bit pattern: 11 10 01 00 11 10 01 11 10 01 11 10 11 10 11 11
Number of 2-bit blocks less than or equal to 00: 1 block(s)
Number of 2-bit blocks less than or equal to 01: 4 block(s)
Number of 2-bit blocks less than or equal to 10: 9 block(s)

Live demo