我有一个非常具体的问题,我希望得到你的意见:
给定一个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个)花费了很多时间,我想加快速度。迭代整数并按块比较可能是一个更糟糕的想法。我有机会进一步提高吗?
答案 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)