【问题标题】:Computing powers of -1-1的计算能力
【发布时间】:2017-09-16 17:23:26
【问题描述】:

实现(-1)^n * a 是否有既定的习惯用法?

pow(-1,n) * a 的明显选择似乎很浪费,(1-2*(n%2)) * a 丑陋且效率也不高(两次乘法和一次加法,而不是仅仅设置符号)。我想我现在会选择n%2 ? -a : a,但引入条件似乎也有点可疑。

【问题讨论】:

  • 如果这与语言无关,为什么要使用特定的语法?可能存在一种可以有效处理(-1)^n * a 的语言。
  • 我会选择 pow(-1,n) * a。读者最容易理解。很难说,因为您不是在谈论特定的语言,但是 pow() 很有可能在其中已经完成了一些优化/特殊情况。例如,查找一个 C 实现,它可能与您所期望的完全不同。
  • 标记这个问题语言不可知论的要点是语言通常同意它们提供的功能,例如atan22<<n.

标签: language-agnostic


【解决方案1】:

对您的编程语言、编译器和 CPU 做出某些假设...

要重复传统的——正确的——智慧,甚至不要考虑优化这类事情,除非你的分析工具说它是一个瓶颈。如果是这样,n % 2 ? -a : a 可能会生成非常高效的代码;即一个AND,一个针对零的测试,一个否定和一个条件移动,AND+测试和否定独立,因此它们可以同时执行。

另一个选项看起来像这样:

zero_or_minus_one = (n << 31) >> 31;
return (a ^ zero_or_minus_one) - zero_or_minus_one;

这假定 32 位整数、算术右移、整数溢出的定义行为、二进制补码表示等。它也可能编译成四个指令(左移、右移、XOR 和减法) ,每个之间都有依赖关系......但对于某些指令集可能会更好;例如,如果您使用 SSE 指令对代码进行矢量化。

顺便说一句,如果您使用特定语言标记,您的问题将获得 很多 更多视图 - 并且可能更有用的答案。

【讨论】:

    【解决方案2】:

    正如其他人所写,在大多数情况下,可读性比性能更重要,编译器、解释器和库在优化方面比大多数人想象的要好。因此pow(-1,n) * a 可能是您平台上的有效解决方案。

    如果你真的有性能问题,你自己的建议n%2 ? -a : a 很好。我没有理由担心条件赋值。

    如果您的语言有位与运算符,您也可以使用n &amp; 1 ? -a : a,即使没有任何优化,它也应该非常有效。很可能在许多平台上,这就是 pow(a,b)a == -1b 是整数的特殊情况下实际所做的。

    【讨论】:

    • 我非常有信心编译器很容易将n%2 转换为n&amp;1。对pow(-1, n) 的信心不足 - 非整数 n 的行为不同。
    猜你喜欢
    • 1970-01-01
    • 2022-08-19
    • 2013-11-16
    • 2015-05-10
    • 1970-01-01
    相关资源
    最近更新 更多