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 - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1.