Skip to main content

calculus and analysis - Problem with numerical evaluation of analytically solved integral, solution way off


The following command in Version 9.0.1:


N[Integrate[x^50*Sin[x], {x, 0, 1}]]

gives $1.4615\times 10^{48}$ which is way off from the correct solution which is between $0$ and $0.5$.



Interestingly the indefinite integral comes out correct and if you increase the precision Mathematica gives an error and the following number: $0.0163$. The same result is given by NIntegrate.


What exactly is the problem here, is this a known issue and is there a workaround?



Answer



This is standard cancellation error (please Google for it). See below for more details.




Take a look at the exact result first:


result = Integrate[x^50*Sin[x], {x, 0, 1}]

(* ==>
16432804687774250383441481995831940788236063969597816674967907249 Cos[1] +

50 (-608281864034267560872252163321295376887552831379210240000000000 +
511851539169698127179811081351899421435935914235737810293853873 Sin[1])

*)

Expand[result]

(* ==>
-30414093201713378043612608166064768844377641568960512000000000000 +
16432804687774250383441481995831940788236063969597816674967907249 Cos[1] +

25592576958484906358990554067594971071796795711786890514692693650 Sin[1]
*)

This is approximately 0.016, a very small number, which arises as a difference of two very large numbers. So now it's clear that we need to work with a very high precision (lots of digits) when carrying out the subtraction, otherwise we'll get what's called catastrophic cancellation and thus an incorrect result. This is a phenomenon you need to learn about and be aware of if you do any kind of numerical work on a computer. Mathematica can do computations with lots of digits to avoid this problem, but systems which always use the CPU's built in floating point arithmetic (machine precision) won't be able to work around the problem simply by increasing precision.


By default, Mathematica uses machine precision when you apply N[...], i.e. approximately 16 digits (strictly, it uses 64-bit IEEE floating point, which implies a 53-bit significand, so the number of decimal digits is $\log_{10} 2^{53}$). In this example you have numbers that have 64 digits to the left of the decimal point, so it's impossible to get a precise result if the result would have the first significant digit two places to the right of the decimal point. That is, even a value as large as $10^{48}$ is as near to zero as makes no difference! Crucially, however, precision tracking is disabled when working with machine numbers (for performance reasons), so that even if catastrophic precision loss occurs, Mathematica has no way of knowing it.


The solution is to use arbitrary precision arithmetic, which you can do by explicitly requesting a precision in N[...]. Mathematica will then automatically increase the number of digits used internally in order to get a result that is precise to at least the number of digits requested.


Let's try it:


N[Expand[result], 10]

(* ==> 0.01628978362 *)


This works fine. But if we use the unexpanded form, it doesn't:


N[result, 10]

(* ==> N::meprec: Internal precision limit $MaxExtraPrecision = 50.`
reached while evaluating ... *)

Mathematica warns you that after internally increasing the precision to the requested precision plus 50 digits (i.e. a total of 60 digits in this case), it still can't get a precise result (so you know that the result it prints might not be correct). We can allow more than 50 digits of precision increase:


Block[{$MaxExtraPrecision = 100}, N[result, 10]]


(* ==> 0.01628978362 *)

Now it works fine.


Note that this precision adjustment is part of the functionality of N, and it will not be done automatically e.g. when carrying out simple arithmetic operations. But, since precision is always tracked for arbitrary-precision values, one can easily check to see if precision loss has occurred by using Precision.


If you use NIntegrate, the system never actually computes an exact closed form solution. It uses numerical methods which in this case will give a precise result even without needing to use a high working precision:


NIntegrate[x^50*Sin[x], {x, 0, 1}]

(* ==> 0.0162898 *)

Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...

calculus and analysis - Integral of the Sinc product

Let us consider the following integral $$ B_n = \int_0^\infty \prod_{k=1,3,5,\dots}^n\frac{\sin (x/k)}{x/k}dx $$ By definition, Sinc[x] == Sin[x]/x , therefore B[n_?OddQ] := Integrate[Product[Sinc[x/k], {k, 1, n, 2}], {x, 0, Infinity}] B /@ Range[1, 13, 2] {Pi/2, Pi/2, Pi/2, Pi/2, Pi/2, Pi/2, Pi/2} OK, everything is fine. But... B[15] 467807924713440738696537864469 Pi/935615849440640907310521750000 What's going on? Answer As Eckhard wrote in comments B[n] is the n-th Borwein integral . (The letter B was not accidental :) ) This funny properties of Borwein integrals is related to the Fourier transform of Sinc function FourierTransform[Sinc[x], x, k] 1/2 Sqrt[Pi/2] (Sign[1 - k] + Sign[1 + k]) Plot[%, {k, -2, 2}, Filling -> 0] which is the box function. The result is $\pi/2$ while the sum $$ 1/3+1/5+\dots+1/n $$ B_n = \frac{\pi}{2} - \pi \bigg(\sum_{k=3,5,\ldots}^n\frac{1}{k} -1\biggr)^\frac{n-1}{2}\prod_{k=3,5,\dots}^n\frac{k}{k-1}. $$ For $n=15$ it is equal to $$ \frac{46780...