Wolfram Blog
Andrew Moylan

Mathematica Q&A Series: Generating Random Numbers

October 5, 2011 — Andrew Moylan, Technical Communication & Strategy

Got questions about Mathematica? The Wolfram Blog has answers! We’ll regularly answer selected questions from users around the web. You can submit your question directly to the Q&A Team.

This week’s question comes from Peter, a secondary school teacher:

How can I generate random integers between -10 and 10, but excluding 0?

Read below or watch this screencast for the answer (we recommend viewing it in full-screen mode):

The built-in function RandomInteger can generate random integers with equal probability in a given range. Here are 50 random integers between -10 and 10:

RandomInteger[{-10, 10}, 50]

4, 8, -10, -6, -3, -4, -3, 0, 1, -4, 0, 2, -1, 7, -10, -1, 1, 6, 5, -4, 2, -5, 5, 2, 10, -5, 4, 10, -8, -4, 3, 1, -10, -1, -5, 10, 4, -7, 2, 0, 6, 9, 6, 5, -7, -6, 2, -4, 8, -2

But, of course, sometimes you get zero. What if you want to exclude zero?

There are several different ways to solve this problem. First, you could simply use RandomInteger as above, and then filter out all the zeroes, using a function like DeleteCases:

DeleteCases[RandomInteger[{-10, 10}, 50], 0]

9, -6, 9, -6, -4, -4, 7, -8, 5, -7, 4, 3, 1, -7, 6, 8, 2, -2, -9, 7, -4, -7, 4, 3, -10, 2, 8, -7, 8, -10, 7, -5, 2, -6, 2, -8, 7, 4, -4, -6, -10, -8, -1, -1, 5, 6, -4

The disadvantage with this approach is that you don’t know in advance how many numbers you’ll get. In this case, we got just 47 nonzero integers:

Length[%]

47

For a better method, start by setting up the list of acceptable integers in advance:

values = Join[Range[-10, -1], Range[1, 10]]

-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Or equivalently:

values = DeleteCases[Range[-10, 10], 0]

-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Then you can use the function RandomChoice to get 50 random selections from the list:

RandomChoice[values, 50]

6, -3, 3, -4, -7, 6, -3, -8, -1, 10, 1, -6, -9, -8, 5, -9, 8, 8, -1, 2, -6, -8, -8, -9, 4, -2, -6, 3, 2, -7, -1, 3, -10, 6, -9, 6, 5, 4, -1, 8, -8, -2, 10, -3, -3, 1, 9, 8, -6, -6

This is a good way to solve this particular problem.

A different, more general approach is to begin with the fact that you want to generate random variates from a certain discrete probability distribution.

dist = ProbabilityDistribution[Boole[x ≠ 0], {x, -10, 10, 1}]

(The last element, 1, in the range specification {x, -10, 10, 1} indicates a discrete distribution.)

The first argument given to ProbabilityDistribution, Boole[x ≠ 0], is a probability density function (PDF) that is zero at x = 0 and constant elsewhere:

DiscretePlot[PDF[dist, x], {x, -10, 10}, AxesOrigin → {-11, 0}]

probability density function that zero at x = 0 and constant elsewhere

Now you can use RandomVariate to generate a list of random variates from this distribution:

RandomVariate[dist, 50]

-1, -8, 4, -8, -7, -4, -5, -6, -1, -8, -2, -1, 10, -4, -3, -7, 5, -1, 8, -6, -2, -2, 3, -10, -10, -4, 8, -8, 3, -6, 8, -6, -10, -7, -10, 5, -6, -6, 6, -10, -7, -5, -2, 3, 5, -3, -6, 3, -2, 6

This approach, using ProbabilityDistribution, is more general because you could use any logical predicate inside Boole:

dist2 = ProbabilityDistribution[Boole[Or[Mod[x, 2] = 0, x ∈ Primes]], {x, 1, 1000, 1}];

This is a uniform distribution over all the integers between 1 and 1000 that are either even or prime. Generate 20 such integers:

RandomVariate[dist2, 20]

-1, 6, -7, 8, 5, 1, -2, 4, 7, 10

There are several other built-in functions for generating random numbers that you can explore. RandomSample gives a random subset of a list, as if you were drawing numbers from a bag without replacing them:

RandomSample[values, 10]

-1, 6, -7, 8, 5, 1, -2, 4, 7, 10

Note how no number is repeated in the random sample.

RandomReal and RandomComplex can be used in a similar way as RandomInteger, to get uniformly distributed random numbers within a specific range:

RandomReal[{0, 3}, 10]

2.53325, 1.08239, 2.60641, 2.2487, 1.32193, 2.13954, 2.46629, 2.15064, 1.17876, 0.69823

And RandomVariate can be used with any probability distribution, whether it be discrete or continuous, single or multivariate. Learn more at the guide page for random number generation.

You can also download this post as a Computable Document Format (CDF) file.

If you have a question you’d like answered in this blog, you can submit it to the Q&A Team. For daily bite-sized Mathematica tips, follow our @MathematicaTip Twitter feed (or follow using RSS).

Posted in: Mathematica Q&A
Leave a Comment

4 Comments


Peter

Thank you! Learning Mathematica is a slightly daunting but very rewarding task, and your quite exhaustive answer helped a lot.

Posted by Peter    October 5, 2011 at 3:04 pm
Simon

As expected, because it’s more general, the RandomVariate solution is a lot slower than the other options. My timings show that RandomChoice[...] is about 5 times faster than DeleteCases[RandomInteger[...],0] and 200 times faster than RandomVariate[...]. Is there any way of optimizing/compiling the RandomVariate solution?

Posted by Simon    October 5, 2011 at 4:58 pm
Juan José Alba

My approach:
RandomInteger[{-10, 9}, 100] /. (x_ /; x >= 0 -> x + 1)

Posted by Juan José Alba    October 5, 2011 at 7:44 pm
Lori “Mathhead” Johnson

And yet another approach:

Table[(-1)^RandomInteger[]*RandomInteger[{1, 10}], {i, 100}]

I use this to generate random integers in expressions:

randInt:=(-1)^RandomInteger[]*RandomInteger[{1, 10}]

then use it in expressions like this:

(x+randInt)*(x+randInt)

and so on…

Posted by Lori "Mathhead" Johnson    October 12, 2011 at 1:29 am


Leave a comment

Loading...

Or continue as a guest (your comment will be held for moderation):