0
from random import *
def main():
    t = 0
    for i in range(1000):  # thousand
        t += random()
    print(t/1000)
main()

I was looking at the source code for a sample program my professor gave me and I came across this RNG. can anyone explain how this RNG works?

Valus Sulav
  • 145
  • 1
  • 2
  • 9
  • It's not stupid at all if you're looking for a Gaussian/normal distribution. – Russell Borogove Sep 25 '14 at 21:14
  • @RussellBorogove Actually it's incredibly stupid. This is the prob/stats equivalent of multiplying two large numbers A and B by adding A to itself B times. There are much better ways to get Gaussians than by summing a thousand uniforms. – pjs Sep 25 '14 at 22:28
  • Your professor seems like a good candidate for someone who could explain the code (s)he wrote :) – dimo414 Sep 26 '14 at 04:21
  • @pjs - perhaps random number generation is *not* the goal of this exercise. Maybe the goal is something else, and Valus has not stated it. Its early in the semester, so I would expect this to be an exercise using control statements and arithmetic. I could be wrong, though. – jww Sep 26 '14 at 06:28
  • @jww There many examples for demonstrating such things that are much better. Even if the idea is to show the Central Limit Theorem, you can see it almost immediately by adding 2 uniforms or 3 uniforms, while looping up to 12 and subtracting 6 gives you a result which is pretty close to a standard normal. 1000 is a pure waste of computing cycles. – pjs Sep 26 '14 at 15:34

4 Answers4

5

If you plotted the points, you would see that this actually produces a Gaussian ("normal") distribution about the mean of the random function.

enter image description here

Generate random numbers following a normal distribution in C/C++ talks about random number generation; it's a pretty common technique to do this if all you have is a uniform number generator like in standard C.

What I've given you here is a histogram of 100,000 values drawn from your function (of course, returned not printed, if you aren't familiar with python). The y axis is the frequency that the value appears, the x axis is the bin of the value. As you can see, the average value is 1/2, and by 3 standard deviations (99.7 percent of the data) we have almost no values in the range. That should be intuitive; we "usually" get 1/2, and very rarely get .99999

Community
  • 1
  • 1
en_Knight
  • 5,301
  • 2
  • 26
  • 46
  • Note that Python has a much faster way to get this sort of distribution: random.gauss(). https://docs.python.org/2/library/random.html#random.gauss – Russell Borogove Sep 25 '14 at 21:16
  • Also, though the docs don't say this, apparently `random.gauss()` is not thread-safe, while `random.normalvariate()` is. (I'm just going by [this StackOverflow answer](http://stackoverflow.com/a/8815748/95852).) – John Y Sep 25 '14 at 21:18
1

Have a look at the documentation. Its quite well written: https://docs.python.org/2/library/random.html

The idea is that that program generates a random number 1000 times which is sufficiently enough to get mean as 0.5

Oliver Blue
  • 677
  • 2
  • 9
  • 22
0

The program is using the Central Limit Theorem - sums of independent and identically distributed random variables X with finite variance asymptotically converge to a normal (a.k.a. Gaussian) distribution whose mean is the sum of the means, and variance is the sum of the variances. Scaling this by N, the number of X's summed, gives the sample mean (a.k.a. average). If the expected value of X is μ and the variance of X is σ2, the expected value of the sample mean is also μ and it has variance σ2 / N.

Since a Uniform(0,1) has mean 0.5 and variance 1/12, your algorithm will generate results that are pretty close to normally distributed with a mean of 0.5 and a variance of 1/12000. Consequently 99.7% of the outcomes should fall within +/-3 standard deviations of the mean, i.e., in the range 0.5+/-0.0274.

This is a ridiculously inefficient way to generate normals. Better alternatives include the Box-Muller method, Polar method, or ziggurat method.

pjs
  • 18,696
  • 4
  • 27
  • 56
-1

The thing making this random is the random() function being called. random() will generate 1 (for most practical purposes) random float between 0 and 1.

>>>random()
0.1759916412898097
>>>random()
0.5489228122596088

etc.

The rest of it is just adding each random to a total and then dividing by the number of randoms, essentially finding the average of all 1000 randoms, which as Cyber pointed out is actually not a random number at all.

Alecg_O
  • 892
  • 1
  • 9
  • 19