Reputation: 60341
Consider a convergent serie in the form:
sum(((-1)^n)*something)
where n
is the index of iteration (n
goes from 1
to infinity
).
If we implement direclty the formula, we have std::pow(-1, n)
but is there a more "rapid" algorithmic trick to implement that ?
Upvotes: 2
Views: 322
Reputation: 47614
The term ((-1)^n)*something
evaluates to -something
for odd n
, or something
for even n
:
n & 1 ? -something : something
If something
is a constant value, then sum(((-1)^n)*something)
evaluates to -something
when the last value of n
is odd, or 0
for an even number of summands:
n & 1 ? -something : 0
In this case, the serie would not be convergent.
Upvotes: 1
Reputation:
I'm assuming that sum(((-1)^n)*something)
is pseudocode, and n
is a variable bound by sum.
Let's extend that notation to sum(n <- [0,1,2,3..], ((-1)^n)*f(n))
. Your best option would probably be to first split this into two sums, that you add together:
sum(n <- [0,2..], ((-1)^n)*f(n)) + sum(n <- [1,3..], ((-1)^n)*f(n))
In the first term, n
is always even, so (-1)^n
will always be +1
. Analogously, in the second term, it will always be -1
. We can now rewrite this as follows:
sum(n <- [0,2..], f(n)) + sum(n <- [1,3..], -f(n))
Since every term in the second sum is multiplied by a constant, we can move that constant out of the sum:
sum(n <- [0,2..], f(n)) - sum(n <- [1,3..], f(n))
Now, let's make sure these sums take the same sequences of indices, and substitute 2*m
and 2*m+1
for n
:
sum(m <- [0,1..], f(2*m)) - sum(m <- [0,1..], f(2*m+1))
Now we can unite these sums again:
sum(m <- [0,1..], f(2*m) - f(2*m+1))
Or, if you want pseudo-C:
T result = 0;
for(m = 0; m < limit; m+=2) {
result += f(m);
result -= f(m+1);
}
This saves you a multiplication by +1
or -1
, as most seem to suggest here. Since your sequence is convergent, taking an extra term should not negatively influence the correctness of the answer.
Upvotes: 6
Reputation: 129314
If you are doing this in a loop, you could simply do:
x = 1; // Assuming we start on n = 0
for(...) // or while(...)
{
sum += x * something;
x = -x;
}
This is most likely a lot faster than doing checks on n - of course, it DOES assume that all n values are iterated over, and you are not skipping a few here and there...
Upvotes: 1
Reputation: 3574
Yeah, there is a magic trick: (-1)^n == 1
if and only if n
is even, and (-1)^n == -1
if and only if n
is odd. Thus:
int p = (n % 2 == 0) ? 1 : -1;
sum(p*something)
Upvotes: 1
Reputation: 183873
Check whether n
is even or odd,
(n % 2 == 0) ? 1 : -1;
does it. If you want to avoid a branch,
1 - 2*(n & 1)
Upvotes: 13