When I ask Mathematica to evaluate
NSum[((-1)^n)/n, {n, 1, 100}]
it returns -0.688172 + 2.11297*10^-16 i
Why is this? (-1)^n is either 1 or -1. I don't know why it is returning a non-real number. Is there a way to avoid this?
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityMachine floating point arithmetic can produce strange results when the numbers get very small. Here are same ways to deal with it.
Suppress insignificant imaginary parts.
NSum[((-1)^n)/n, {n, 1, 100}] // Chop
-0.688172
Work with exact numbers until the very end (slower).
Sum[((-1)^n)/n, {n, 1, 100}] // N
-0.688172
Use Mathematica's arbitrary precision arithmetic rather than machine arithmetic.
NSum[((-1)^n)/n, {n, 1, 100}, WorkingPrecision -> 16]
-0.688172179310
Use the special method that NSum
has for maintaining precision with series that have terms with alternating signs. This is likely to be the best solution for this particular sum.
NSum[((-1)^n)/n, {n, 1, 100}, Method -> "AlternatingSigns"]
-0.688172
NSum
uses a combination of analytic and numeric methods. For instance, it computes
(-1)^102.
(* 1. - 1.95968*10^-14 I *)
with a real exponent instead of an exact integer. It's the same as Exp[102. Log[-1]]
, which is the same as Exp[I * 102. * Pi]
, for that is how Power
is computed when the exponent is Real
. Rounding error in 102. * Pi
introduces a small, complex part in the final result.
For more, see the output of
Trace[NSum[((-1)^n)/n, {n, 1, 100}]]
As @kglr pointed out, the way to make Mathematica handle the -1
power appropriately is with
NSum[((-1)^n)/n, {n, 1, 100}, Method -> "AlternatingSigns"]
The fact that Power
with a negative base is going to be a complex-valued function when the exponent is an approximate Real
can be countered, given the terms are real, by using Re
:
NSum[Re[((-1)^n)/n], {n, 1, 100}]
(* -0.688172 *)
A different approach that uses exact exponents and Real
base:
Total[(-1.)^#/# &@Range[100]]
(* -0.688172 *)
Integer powers are treated differently than floating-point powers. Total
tends to be a better way to approach small finite sums.
exp(102*log(-1))
in Maple? In Matlab, exp(..)
gives the Mathematica result, but (-1).^102
gives 1
. I think in Matlab and maybe Maple, -1
raised to a floating-point whole number is treated as a special case. OTOH, (-1)^10000000000000001
in Matlab yields 1
. -- I rather think in this case, Mathematica's handling is predictably consistent and normal: a^b == Exp[b * Log[a]]
and Log[-1] = Pi * I
. One should expect a rounding error of at most 102*Pi*$MachineEpsilon/2
, which is about what we get. IMO, the issue not floating point, but the def. of (-1)^x
.
$\endgroup$
Feb 25, 2018 at 3:32
exp(102*log(-1))
Maple gives 1
here is screen shot !Mathematica graphics
$\endgroup$
10^-8
on the floating-point input; that seems like a large error. Does Maple use single-precision? I mean Mathematica gives 1
, too: i.stack.imgur.com/IoQZv.png
$\endgroup$
Feb 25, 2018 at 4:05
Digits
setting. By default this is set to 10
. Here is the same thing, when I changed it to 16
!Mathematica graphics Maple software floating point is what used by default. Now it give similar value as Mathematica. To use hardware floating point, there is evalfh
also.
$\endgroup$
I want to mention that this sum has a closed form in terms of Mathematica functions
(-1)^n*LerchPhi[-1, 1, 1 + n] - Log[2]
As already carefully pointed out by Michael, the (-1)^n
part introduces the small imaginary parts when you apply it to real values. If you are interested in a approximate result, the easiest way is to calculate the above term for integers and then taking N
.
f[n_Integer] := N[(-1)^n*LerchPhi[-1, 1, 1 + n] - Log[2]]
f[100]
(* -0.688172 *)
However, calculating LerchPhi
should be faster when calculated with approximate numbers in the first place. So the other solution is to put the N
inside LerchPhi
. Therefore, the better alternative if you want to calculate this for large n
might be this
f2[n_Integer] := (-1)^n*LerchPhi[-1, 1, 1 + N[n]] - Log[2]
A quick comparison shows, that I can easily calculate 2^20
in half a second
f2[2^20] // AbsoluteTiming
(* {0.508786, -0.693147} *)
while the exact computation of f
needs about 300x the time of this
f[2^20] // AbsoluteTiming
(* {147.191, -0.693147} *)
Runtime-wise, nothing will beat NSum
if it implicitly contains a more expensive function. Therefore, my last point is to mention that you can easily split your sum into to parts: All positive terms and all negative terms. With this, you get completely rid of the (-1)^n
term and no Chop
is necessary
nn = 100;
NSum[1/n, {n, 2, nn, 2}] - NSum[1/n, {n, 1, nn - 1, 2}]
(* -0.688172 *)
1/n - 1/(n+1)
and simplify to 1/n/(n+1)
, and best to sort from smallest to largest (here that means iterate n
in decreasing order)
$\endgroup$
Feb 26, 2018 at 1:00
(-1)^n
term is very valuable.
$\endgroup$
(1/n) - (1/(n+1))
or 1/n/(n+1)
?
$\endgroup$
Feb 28, 2018 at 16:15
NSum[((-1)^n)/n, {n, 1, 100}, Method -> "AlternatingSigns"]
orN@Sum[((-1)^n)/n, {n, 1, 100}]
$\endgroup$N@Sum
orChop@NSum
. $\endgroup$Sum
gives an exact result (check it), to which you then applyN
. And I guessNSum
treats every component with machine precision, so there are more opportunities to introduce rounding errors. Interestingly, however,Sum[N@....]
andNSum[((-1.)....
give correct results. SoNSum
must have a different implementation. $\endgroup$