22

How can I define a function f(x) in Mathematica that gives 1 if x is in [-5, -4] or [1, 3] and 0 otherwise? It's probably something simple but I just can't figure it out!

Dunda
  • 355
  • 1
  • 2
  • 7
  • If statements work just fine, moreover, in an If statement, one can define only those piecewise variable ranges that are defined for a function, such that for plotting and other conditions no superfluous range definitions are needed. – Carl May 03 '20 at 10:23

3 Answers3

33

The basic construction you want is Piecewise, in particular the function you were asking for can be written as

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

or

f[x_] := Piecewise[{{1, -5 <= x <= -3 || 1 <= x <= 3}}, 0]

Note that the final argument, 0 defines the default (or "else") value is not needed because the default default is 0.

Also note that although Piecewise and Which are very similar in form, Piecewise is for constructing functions, while Which is for programming. Piecewise will play nicer with integration, simplification etc..., it also has the proper left-brace mathematical notation, see the examples in the documentation.


Since the piecewise function you want is quite simple, it could also be constructed from step functions like Boole, UnitStep and UnitBox, e.g.

UnitBox[(x + 4)/2] + UnitBox[(x - 2)/2]

These are just special cases of Piecewise, as shown by PiecewiseExpand

In[19]:= f[x] == UnitBox[(x+4)/2] + UnitBox[(x-2)/2]//PiecewiseExpand//Simplify
Out[19]= True

Alternatively, you can use switching functions like HeavisideTheta or HeavisidePi, e.g.

HeavisidePi[(x + 4)/2] + HeavisidePi[(x - 2)/2]

which are nice, because if treating the function as a distribution, then its derivative will return the correct combination of Dirac delta functions.


For more discussion see the tutorial Piecewise Functions.

Simon
  • 14,631
  • 4
  • 41
  • 101
  • 1
    I'm not sure if etiquette here allows replying just to say "thanks" but I'll do that. :) The depth of Mathematica (and your knowledge of it) is overwhelming. – Dunda Oct 04 '11 at 01:14
  • @yahelc: Thanks for that final 10pts! (You'd think that powers of 2 would be more important on a programmers site than powers of 10...) – Simon Dec 09 '11 at 23:06
13

Although Simon's answer is the canonical and correct one, here are another two options:

f[x_] := 1 /; IntervalMemberQ[Interval[{-5, -3}, {1, 3}], x]
f[x_?NumericQ] := 0

or

f[x_] := If[-5 <= x <= -3 || 1 <= x <= 3, 1, 0]

Edit:
Note that the first option depends on the order that the definitions were entered (thanks Sjoerd for pointing this out). A similar solution that does not have this problem and will also work correctly when supplied an Interval as input is

f[x_] := 0 /; !IntervalMemberQ[Interval[{-5, -3}, {1, 3}], x]
f[x_] := 1 /;  IntervalMemberQ[Interval[{-5, -3}, {1, 3}], x]
Simon
  • 14,631
  • 4
  • 41
  • 101
Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
  • 2
    +1 for [IntervalMemberQ](http://reference.wolfram.com/mathematica/ref/IntervalMemberQ.html). I never seem to use the [Interval](http://reference.wolfram.com/mathematica/ref/Interval.html) arithmetic in Mathematica... – Simon Oct 03 '11 at 05:49
  • Another issue with the first example is that it's not equivalent to the `If[...]` version or the `Piecewise` one. For regions not within the `Interval`, `f[x]` is undefined. – Mike Bailey Oct 03 '11 at 05:56
  • @belisarius: Made a couple of small changes - hope that's ok. – Simon Oct 03 '11 at 06:09
  • @belisarius: But the `Piecewise` function remains unevaluated for symbolic arguments - your `f[x_]:=0` did not... – Simon Oct 03 '11 at 06:15
  • @belisarius: Ah... told you I haven't used intervals much, I didn't think of this problem. There should be a built in predicate for `NumericalIntervalQ` that includes the degenerate case of `NumericQ`... – Simon Oct 03 '11 at 06:27
  • @simon I don't think your edit is correct. Without the ?NumericQ pattern the first definition was more general than the second one causing the second one to be tried first during evaluation. With the addition of ?NumericQ this order is now changed and as far as I can see mma now executes the first one for every numeric argument returning 0 regardless of whether the number is in the interval or not. – Sjoerd C. de Vries Oct 03 '11 at 20:18
  • @Sjoerd: Ouch! You're right. Mma can't decide which definition is more general, so it keeps them in the order that they were entered. Reverse the order, like it must have been in my test code, and it works! – Simon Oct 05 '11 at 22:10
  • @belisarius: By the way, sorry for making a mess of your answer. From now on, I'll try to resist the urge of thinking that I know better! – Simon Oct 06 '11 at 03:23
  • @Simon I always thought knowledge is created iff: 1) we have enough self-confidence to be able to think that we can come up with a better solution to a problem and 2) we have enough humility to accept that we could be wrong. As far as those two conditions are met, you will always find me supporting the proposal of a new idea. As for the methodology (editing somebody's else answer), it is what the mechanics of the site allows, so don't mind about it. Of course a friendly discussion by a blackboard could be better, but that again would surely seemed harsh if suggested in Aristotle's Academia. – Dr. belisarius Oct 06 '11 at 04:52
0

All is good and well but as a general rule of the thumb one should try always the simplest approach and keep away as possible from the sophisticated high level programming. In this particular situation I mean the following:

f[x_ /; -5 <= x <= -3] = 0 etc ... etc

alinux
  • 1