(-1)^ c在c ++中取幂

时间:2013-01-05 23:34:33

标签: c++ math optimization

考虑以下形式的收敛系列:

sum(((-1)^n)*something) 

其中n是迭代索引(n1变为infinity)。

如果我们实现direclty公式,我们有std::pow(-1, n)但是有更多“快速”的算法技巧来实现它吗?

5 个答案:

答案 0 :(得分:13)

检查n是偶数还是奇数,

(n % 2 == 0) ? 1 : -1;

做到了。如果你想避免分支,

1 - 2*(n & 1)

答案 1 :(得分:6)

我假设sum(((-1)^n)*something)是伪代码,而n是一个受和的约束变量。

让我们将该符号扩展为sum(n <- [0,1,2,3..], ((-1)^n)*f(n))。你最好的选择可能是首先把它分成两个,你加在一起:

sum(n <- [0,2..], ((-1)^n)*f(n)) + sum(n <- [1,3..], ((-1)^n)*f(n))

在第一个字词中,n始终是偶数,因此(-1)^n始终为+1。类似地,在第二个词中,它总是-1。我们现在可以按如下方式重写:

sum(n <- [0,2..], f(n)) + sum(n <- [1,3..], -f(n))

由于第二个和中的每个项乘以一个常数,我们可以将该常数移出总和:

sum(n <- [0,2..], f(n)) - sum(n <- [1,3..], f(n))

现在,让我们确保这些总和采用相同的索引序列,并将2*m2*m+1替换为n

sum(m <- [0,1..], f(2*m)) - sum(m <- [0,1..], f(2*m+1))

现在我们可以再次联合这些总和:

sum(m <- [0,1..], f(2*m) - f(2*m+1))

或者,如果你想要伪C:

T result = 0;
for(m = 0; m < limit; m+=2) {
    result += f(m);
    result -= f(m+1);
}

这可以为您节省乘以+1-1,正如大多数人似乎在此建议的那样。由于你的序列是收敛的,所以加一个额外的术语不应该对答案的正确性产生负面影响。

答案 2 :(得分:1)

是的,有一个神奇的伎俩:(-1)^n == 1当且仅当n是偶数时,(-1)^n == -1当且仅当n是奇数时。因此:

int p = (n % 2 == 0) ? 1 : -1;
sum(p*something)

答案 3 :(得分:1)

对于奇数((-1)^n)*something-something一词评估为n,对{偶数something评估为n

n & 1 ? -something : something

如果something是一个常数值,那么当sum(((-1)^n)*something)的最后一个值为奇数时,-something会计算为n,对于偶数,0会计算为n & 1 ? -something : 0 of summands:

{{1}}

在这种情况下,系列不会收敛。

答案 4 :(得分:1)

如果您在循环中执行此操作,则可以执行以下操作:

x = 1;   // Assuming we start on n = 0
for(...)    // or while(...)
{
   sum += x * something;

   x = -x;
}

这很可能比对n进行检查要快得多 - 当然,它假设所有n个值都被迭代,并且你不会在这里和那里跳过一些......