c++ - 查找以 2 为底的对数向上舍入为整数,与向上舍入到 2 的幂并查找最高设置位相同吗?

标签 c++ bit logarithm

类似地,值向下舍入到 2 的幂并找到最右边的设置位相当于以 2 为底的对数向下舍入到整数。这是正确的吗?

我认为这会起作用,对于任何数字四舍五入到 2 的幂,并执行 C++ 中的 countr_zero() 或 MSVC 中的 bitscan 函数或 GCC 中的 __builtin_ctz()。这行得通吗?这肯定比 log 函数要好得多,log 函数(根据我的理解)可能是 CPU 可以执行的最慢的计算。

有趣的是,这样做本身涉及相当多的步骤:

//Round up to power of 2
unsigned int v; // compute the next highest power of 2 of 32-bit v

v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;

虽然 count_zero 看起来像:

usize countr_zero(u64 x) {
  if (x == 0)
    return 64;
#ifdef __GNUC__
  return __builtin_ctzll(x);
#else
  constexpr std::array<usize, 64> table = {
      0,  1,  2,  7,  3,  13, 8,  27, 4,  33, 14, 36, 9,  49, 28, 19,
      5,  25, 34, 17, 15, 53, 37, 55, 10, 46, 50, 39, 29, 42, 20, 57,
      63, 6,  12, 26, 32, 35, 48, 18, 24, 16, 52, 54, 45, 38, 41, 56,
      62, 11, 31, 47, 23, 51, 44, 40, 61, 30, 22, 43, 60, 21, 59, 58};
  return table[(x & ~x + 1) * 0x218A7A392DD9ABF >> 58 & 0x3F];
#endif
}

但它仍然比调用 log 并转换为整数更好,对吗?

最佳答案

是的,

  • 四舍五入到下一个较低的 2 次方并取对数相当于取取底对数,并且
  • 四舍五入到下一个更大的 2 的幂并取对数相当于取上限对数。

仅当我们忽略 log2(0.1) 的边缘情况时,这些等价才成立,其中 floor(log2(0.1)) 不同log2(0).

请注意,您可以使用 std::bit_width(x) - 1 获取任何整数 x 的底二进制对数。上限对数也可以通过这种方式获得;如果 x 不是 2 的幂,则只需递增即可。

But it still has to be better than calling log and converting to integer, right?

并不明显它会变慢。浮点运算可能有硬件支持,并且原则上可以更快。尤其是 sqrt 速度快得惊人。我不知道有任何架构具有快速内置对数指令。 x87指令相对较慢。

如有疑问,您应该进行分析。

另请参阅

关于c++ - 查找以 2 为底的对数向上舍入为整数,与向上舍入到 2 的幂并查找最高设置位相同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77243973/

相关文章:

c++ - 如何检查数据库是否存在?

c++ - C/C++ 位数组或位 vector

c - 我怎样才能屏蔽位?

c++ - 如何比较 C++ 中 log() 和 fp 除法的性能?

c++ - boost::interprocess : Allocating Shared Memory within a loop

c++ - 按下键或移动鼠标时游戏速度变慢

python - 以对数方式拆分 Python 列表

c++ - C++ 中非常快速的近似对数(自然对数)函数?

c++ - 单向链表 C++

c - C 中的位打包