C/ c++中最低有效位集的有效除法
Efficient Division by Least Significant Bit set in C/C++
我想尽快执行以下操作
x / LSB(x)
,其中x
是编译时未知的整数值,LSB(x) = x & -x
。(或者,该操作相当于偶数除以2的最高幂<= x。)我正在寻找一个合理的可移植的解决方案(没有编译器的内在/内置像GCC的__builtin_clz
或类似的)。
我担心的是下面的简单实现
x / (x & -x)
仍然会导致开销很大的除法,因为编译器可能没有意识到除法实际上相当于向右移动除数后面的0的个数。
如果我的担心是合理的,那么实现它的更有效的方法是什么?
我将欣赏一个解决方案,很容易扩展到整数类型的大小32位,64位,128位,…
x >>= ffs(x)-1;
ffs
函数符合4.3BSD, POSIX.1-2001。
如果x
为0,它将不起作用。
如果您不想依赖于CLZ (count前导零)硬件指令,您可以按照本答案中描述的方式计算前导零。查找和乘以一个神奇的数字是非常快的。我将在这里重新发布代码:
unsigned x; // input to clz
unsigned c; // output of clz
static const unsigned MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
c = MultiplyDeBruijnBitPosition[((unsigned)((x & -x) * 0x077CB531U)) >> 27];
计算完前导零后,就不再需要使用除法指令了。相反,您可以通过c
向右移动值。也就是说(去掉一个不需要的临时值),代码变成这样:
static const unsigned MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
x >>= MultiplyDeBruijnBitPosition[((unsigned)((x & -x) * 0x077CB531U)) >> 27]; // x /= LSB(x)
相关文章:
- 欧拉项目#8答案是大以获得有效答案
- 调整大小后指向元素值的指针unordered_map有效?
- 为什么是0;C++中的有效语句
- 最高有效数字侧的第N位
- GCC对可能有效的代码抛出init list生存期警告
- 有效地使用std::unordered_map来插入或增加键的值
- c++中O(n^(1/3))中一个数的除数的有效计数
- 使用无符号字符数组有效存储内存
- 自定义先决条件对移动分配运算符有效吗
- 在除法中不需要四舍五入
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 为什么这种直接初始化有效?(C++17)
- 递归函数有效,但无法记忆
- 在C++中初始化向量映射的最有效方法
- 如果变量名称不跟在 char* 后面,const char* 是否有效?
- 在TFHE(完全快速同态加密)上执行除法
- 钳制迭代器是否有效
- 使用 int 表示浮点除法 C++
- C/ c++中最低有效位集的有效除法