许多算法需要计算(-1)^n
(均为整数),通常作为系列中的一个因素。即,-1
对于奇数 n 和偶数 n的因子1
。在 C++ 环境中,经常会看到:
#include<iostream>
#include<cmath>
int main(){
int n = 13;
std::cout << std::pow(-1, n) << std::endl;
}
什么是更好的或通常的约定?(或者是其他东西),
std::pow(-1, n)
std::pow(-1, n%2)
(n%2?-1:1)
(1-2*(n%2)) // (gives incorrect value for negative n)
编辑:
此外,用户@SeverinPappadeux 提出了另一种基于(全局?)数组查找的替代方案。我的版本是:
const int res[] {-1, 1, -1}; // three elements are needed for negative modulo results
const int* const m1pow = res + 1;
...
m1pow[n%2]
这可能不会解决问题,但是通过使用发出的代码,我们可以放弃一些选项。
首先没有优化,最终的竞争者是:
1 - ((n & 1) << 1);
(7次操作,无内存访问)
mov eax, DWORD PTR [rbp-20]
add eax, eax
and eax, 2
mov edx, 1
sub edx, eax
mov eax, edx
mov DWORD PTR [rbp-16], eax
和
retvals[n&1];
(5个操作,内存--寄存器?--访问)
mov eax, DWORD PTR [rbp-20]
and eax, 1
cdqe
mov eax, DWORD PTR main::retvals[0+rax*4]
mov DWORD PTR [rbp-8], eax
现在进行优化(-O3)
1 - ((n & 1) << 1);
(4次操作,无内存访问)
add edx, edx
mov ebp, 1
and edx, 2
sub ebp, edx
.
retvals[n&1];
(4个操作,内存--寄存器?--访问)
mov eax, edx
and eax, 1
movsx rcx, eax
mov r12d, DWORD PTR main::retvals[0+rcx*4]
.
n%2?-1:1;
(4个操作,无内存访问)
cmp eax, 1
sbb ebx, ebx
and ebx, 2
sub ebx, 1
测试在这里。我不得不做一些杂技来编写有意义的代码,这些代码不会一起省略操作。
结论(暂时)
所以最后取决于关卡优化和表现力:
1 - ((n & 1) << 1);
总是很好但不是很有表现力。retvals[n&1];
为内存访问付出了代价。n%2?-1:1;
富有表现力且很好,但只有优化。