Wolfram Computation Meets Knowledge

Mathematica Q&A Series: Generating Random Numbers

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.

Comments

Join the discussion

!Please enter your comment (at least 5 characters).

!Please enter your name.

!Please enter a valid email address.

8 comments

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

    Reply
  2. 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?

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

    Reply
  4. 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…

    Reply
  5. How to convert RandomReal to RandomInteger?

    Reply
  6. Is there any way to use the RandomInteger function such that once an integer has been drawn, it cannot be drawn again. For example, I am looking to use the RandomInteger to draw 12 integers, between 1 & 12, such that each number is only drawn once. Thanks.

    Reply
  7. how to generate 3*3 matrix only for-1 and +1 for random integer

    Reply