Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bug in NIntegrate[]?

160 views
Skip to first unread message

GS

unread,
Jun 15, 2012, 3:42:18 AM6/15/12
to
I define the function f[x] as follows:

f[x_] := 0 /; x < 0 || x > 1;
f[x_] := 1

It is zero outside of the interval [0,1]. This can be verified by plotting
Plot[f[x], {x, -1, 2}]

Now I integrate it from -1 to 2:
In[270]:= NIntegrate[f[x], {x, -1, 2}]
Out[270]= 3.

The result should be 1, but it is 3. Clearly Mathematica ignores the fact that f[x] is zero outside of [0,1].

This caused a lot of headache for me recently when I encountered such behavior in one of my research code.
GS

Bill Rowe

unread,
Jun 15, 2012, 3:31:14 PM6/15/12
to
This does appear to be a bug. Instead of using logical operators
to define your function why not define it in terms of
HeavisideTheta, i.e.

g[x_] := HeavisideTheta[x] - HeavisideTheta[x - 1]

The advantage of this approach is Mathematica know how to
integrate and differentiate HeavisideTheta. That is:

In[6]:= Integrate[g[x], {x, -2, 1}]

Out[6]= 1

Note, NIntegrate does have problems with this definition. That is

In[7]:= NIntegrate[g[x], {x, -2, 1}]

Out[7]= 1.00024

with a warning about failure to converge with 9 recursive bisections


Andrew Moylan

unread,
Jun 15, 2012, 3:32:46 PM6/15/12
to
This part of your definition,

f[x_] := 1

applies to *symbolic* values of x such as in f[x]. Therefore the evaluation precedes effectively along these lines:

NIntegrate[f[x], {x, -1, 2}]
=> NIntegrate[1, {x, -1, 2}]
=> 3.

To fix it:

One option is to restrict the class of cases where f[x] == 1 to only numbers:

Clear[f]
f[x_] := 0 /; x < 0 || x > 1
f[x_] := 1 /; Element[x, Reals]

This is not ideal (you will see NIntegrate works hard to locate the discontinuities at x==0 and x==1).

Better is to use Mathematica's piecewise functions: Piecewise, If, etc.

In[5]:= g[x_] := If[x < 0 || x > 1, 0, 1]

In[6]:= NIntegrate[g[x], {x, -1, 2}]
Out[6]= 1.

This is because NIntegrate recognizes such functions as likely sources of discontinuities and uses symbolic processing to split them up / simplify them first.

A Retey

unread,
Jun 15, 2012, 3:33:16 PM6/15/12
to
Hi,
Another variant of the most frequently asked question :-). NIntegrate does evaluate the integrand symbolically, if not told otherwise. That symbolic evaluation will return 1 in your case:

In:=f[x]
Out:= 1

Since NIntegrate doesn't seem to accept the option Evaluated->False as some other functions which have the same problem do, you need to define the function so it only evaluates for numeric arguments:

ClearAll@f
f[x_?NumericQ] := 0 /; x < 0 || x > 1;
f[x_?NumericQ] := 1

That will make NIntegrate behave as expected (it will complain about bad convergence, but that I'd consider expected behaviour for that function :-). Note that it can do better if you use more "mathematical" ways to define your function, e.g. UnitStep, UnitBox or HeavsideTheta.

hth,

albert


Tomas Garza

unread,
Jun 15, 2012, 3:35:50 PM6/15/12
to

A quick and ready answer: use Piecewise.
In[1]:= NIntegrate[Piecewise[{{1,0<x<=1}}],{x,-2,1}]Out[1]= 1.
-Tomas

> Date: Fri, 15 Jun 2012 03:41:03 -0400
> From: voka...@gmail.com
> Subject: Bug in NIntegrate[]?
> To: math...@smc.vnet.net

Andrzej Kozlowski

unread,
Jun 15, 2012, 3:38:22 PM6/15/12
to

On 15 Jun 2012, at 09:41, GS wrote:

> I define the function f[x] as follows:
>
> f[x_] := 0 /; x < 0 || x > 1;
> f[x_] := 1
>
> It is zero outside of the interval [0,1]. This can be verified by plotting
> Plot[f[x], {x, -1, 2}]
>
> Now I integrate it from -1 to 2:
> In[270]:= NIntegrate[f[x], {x, -1, 2}]
> Out[270]= 3.
>
> The result should be 1, but it is 3. Clearly Mathematica ignores the fact that f[x] is zero outside of [0,1].
>
> This caused a lot of headache for me recently when I encountered such behavior in one of my research code.
> GS
>

To put it in a nutshell: this is not a bug but the wrong way to do what you are trying to do. Pattern based definitions are not suitable for use in mathematical computations. What happens in your case is that Mathematica tries to evaluate the function with symbolic argument and finds that the pattern condition does not hold, it then uses the second alternative and integrates the function 1 getting the answer 3. You can avoid this by restricting your definition only to numerical input:


f[x_?NumberQ] := 0 /; x < 0 || x > 1;
f[x_?NumberQ] := 1

In[19]:= NIntegrate[f[x], {x, -1, 2}]

During evaluation of In[19]:= NIntegrate::slwcon: Numerical integration converging too slowly; suspect one of the following: singularity, value of the integration is 0, highly oscillatory integrand, or WorkingPrecision too small. >>

During evaluation of In[19]:= NIntegrate::ncvb: NIntegrate failed to converge to prescribed accuracy after 9 recursive bisections in x near {x} = {1.00386}. NIntegrate obtained 0.999525 and 0.000761127 for the integral and error estimates. >>

0.999525

The answer is better but still this is hopelessly wrong approach. The right approach is to use a proper mathematica function intended for this purpose, such as Piecewise, UnitStep etc, e.g.

f[x_] := Piecewise[{{0, x < 0 || x > 1}}, 1]

NIntegrate[f[x], {x, -1, 2}]

1.

Even better, you can do:

Integrate[f[x], {x, -1, 2}]

1


Andrzej Kozlowski=

Bob Hanlon

unread,
Jun 15, 2012, 3:38:53 PM6/15/12
to
NIntegrate first tries to evaluate its argument symbolically and evaluates to 1 since your definition defines f as one for symbolic input.

You could change your default to

f[x_?NumericQ] = 1;

to preclude evaluation for symbolic input; however, it would be better to define f using Piecewise.

f[x_] := Piecewise[{{1, 0 <= x <= 1}}]


Bob Hanlon

Sseziwa Mukasa

unread,
Jun 15, 2012, 3:36:51 PM6/15/12
to
You ran into the issue of calling f with a non-numeric argument, there are still issues due to the discontinuities but:

(Debug) In[14]:= f[x_?NumericQ]:=0/;x<0||x>1
f[x_?NumericQ]:=1
(Debug) In[16]:= NIntegrate[f[x],{x,-1,2}]
(Debug) During evaluation of In[16]:= NIntegrate::slwcon: Numerical integration converging too slowly; suspect one of the following: singularity, value of the integration is 0, highly oscillatory integrand, or WorkingPrecision too small. >>
(Debug) During evaluation of In[16]:= NIntegrate::ncvb: NIntegrate
failed to converge to prescribed accuracy after 9 recursive bisections in x near {x} {1.00386}. NIntegrate obtained 0.9995253309911655` and 0.0007611273421692226` for the integral and error estimates. >>
(Debug) Out[16]= 0.999525

Regards,
Ssezi

Gerry Flanagan

unread,
Jun 15, 2012, 3:30:12 PM6/15/12
to
Good reason to use Piecewise
f[x_] := Piecewise[{{0, x < 0 || x > 1}, {1, True}}]
Integrates correctly.

Gerry F.
0 new messages