使用按位运算求 n = 2**x 的指数 [n 以 2 为底的对数]

2023-11-21

有没有一种直接的方法可以仅使用按位运算从 2 的幂中提取指数?

EDIT:虽然问题最初是关于按位运算的,但如果您想知道,该线程也值得一读“在 Y = 2 的情况下找到 X 的最快方法是什么X 在Python中?"**

我目前正在尝试优化例程(拉宾-米勒素性测试)这减少了偶数表格中的 N2**s * d。我可以得到2**s部分由:

two_power_s = N & -N

但我找不到一种方法来提取“s“使用按位运算。我目前正在测试但不太满意的解决方法(它们都非常慢)是:

  • 使用对数函数
  • 操作 2**s 的二进制表示(即计算尾随零)
  • 循环除以 2,直到结果为 1

我正在使用 python,但我想这个问题的答案应该与语言无关。


“语言不可知论”和担心性能几乎是不相容的概念。

大多数现代处理器都有 CLZ 指令,“计算前导零”。在 GCC 中,您可以使用 __builtin_clz(x) 来实现它(对于缺少 clz 的目标,它也会生成合理的(如果不是最快的)代码)。请注意,此 CLZ 未定义为零,因此如果它在您的应用程序中很重要,您将需要一个额外的分支来捕获这种情况。

在CELT(http://celt-codec.org)我们用于缺少 CLZ 的编译器的无分支 CLZ 是由 Timothy B. Terriberry 编写的:


int ilog(uint32 _v){
  int ret;
  int m;
  ret=!!_v;
  m=!!(_v&0xFFFF0000)<<4;
  _v>>=m;
  ret|=m;
  m=!!(_v&0xFF00)<<3;
  _v>>=m;
  ret|=m;
  m=!!(_v&0xF0)<<2;
  _v>>=m;
  ret|=m;
  m=!!(_v&0xC)<<1;
  _v>>=m;
  ret|=m;
  ret+=!!(_v&0x2);
  return ret;
}

(评论表明,这比分支版本和基于查找表的版本更快)

但如果性能如此关键,您可能不应该在 python 中实现这部分代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用按位运算求 n = 2**x 的指数 [n 以 2 为底的对数] 的相关文章

随机推荐