25

I want to generate random numbers in the range -1, 1 and want each one to have equal probability of being generated. I.e. I don't want the extremes to be less likely to come up. What is the best way of doing this?

So far, I have used:

2 * numpy.random.rand() - 1 

and also:

2 * numpy.random.random_sample() - 1 
2
  • 2
    Did you have any problem with the approach you used? Commented Jul 26, 2012 at 15:48
  • @ Sven the problem is that I can't be sure that the extremes are as likely to be chosen as all the other possibilities. Commented Jul 26, 2012 at 15:51

4 Answers 4

34

Your approach is fine. An alternative is to use the function numpy.random.uniform():

>>> numpy.random.uniform(-1, 1, size=10) array([-0.92592953, -0.6045348 , -0.52860837, 0.00321798, 0.16050848, -0.50421058, 0.06754615, 0.46329675, -0.40952318, 0.49804386]) 

Regarding the probability for the extremes: If it would be idealised, continuous random numbers, the probability to get one of the extremes would be 0. Since floating point numbers are a discretisation of the continuous real numbers, in realitiy there is some positive probability to get some of the extremes. This is some form of discretisation error, and it is almost certain that this error will be dwarved by other errors in your simulation. Stop worrying!

Sign up to request clarification or add additional context in comments.

5 Comments

@wok: Added a comment on the extremes.
Thanks Sven. I will try and stop worrying :-) but easily said than done.
Note that in both methods the interval is half-open, so the upper bound will be produced with probability 0.
@ecatmur: For the specific values -1.0 and 1.0 as boundaries, this is true. For other values, the upper boundary might also be produced due to rounding (I know the documentation says something else, but the documentation is wrong). Anyway, the chances of hitting any of the boundary values are negligible, so this only matters in practice if you want to avoid some error state, like a division by zero.
Exactly the method I needed, and so much clearer than the numpy documentation.
5

Note that numpy.random.rand allows to generate multiple samples from a uniform distribution at one call:

>>> np.random.rand(5) array([ 0.69093485, 0.24590705, 0.02013208, 0.06921124, 0.73329277]) 

It also allows to generate samples in a given shape:

>>> np.random.rand(3,2) array([[ 0.14022471, 0.96360618], [ 0.37601032, 0.25528411], [ 0.49313049, 0.94909878]]) 

As You said, uniformly distributed random numbers between [-1, 1) can be generated with:

>>> 2 * np.random.rand(5) - 1 array([ 0.86704088, -0.65406928, -0.02814943, 0.74080741, -0.14416581]) 

Comments

3

From the documentation for numpy.random.random_sample:

Results are from the “continuous uniform” distribution over the stated interval. To sample Unif[A, b), b > a multiply the output of random_sample by (b-a) and add a:

 (b - a) * random_sample() + a 

Per Sven Marnach's answer, the documentation probably needs updating to reference numpy.random.uniform.

Comments

0

To ensure that the extremes of range [-1, 1] are included, I randomly generate a numpy array of integers in the range [0, 200000001[. The value of the latter integer depends on the final numpy data type that is desired. Here, I take the numpy float64, which is the default type used for numpy arrays. Then, I divide the numpy array with 100000000 to generate floats and subtract with unity. Code for this is:

>>> import numpy as np >>> number = ((np.random.randint(low=0, high=200000001, size=5)) / 100000000) - 1 >>> print(number) [-0.65960772 0.30378946 -0.05171788 -0.40737182 0.12998227] 

Make sure not to transform these numpy floats to python floats to avoid rounding errors.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.