views:

2934

answers:

8

For 6 years I've had a random number generator page on my website. For a long time, it was the first or second result on Google for "random number generator" and has been used to decide dozens, if not hundreds of contests and drawings on discussion forums and blogs (I know because I see the referrers in my web logs and usually go take a look).

Today, someone emailed me to tell me it may not be as random as I thought. She tried generating very large random numbers (e.g., between 1 and 10000000000000000000) and found that they were almost always the same number of digits. Indeed, I wrapped the function in a loop so I could generate thousands of numbers and sure enough, for very large numbers, the variation was only about 2 orders of magnitude.

Why?

Here is the looping version, so you can try it out for yourself:

http://andrew.hedges.name/experiments/random/randomness.html

It includes both a straightforward implementation taken from the Mozilla Developer Center and some code from 1997 that I swiped off a web page that no longer exists (Paul Houle's "Central Randomizer 1.3"). View source to see how each method works.

I've read here and elsewhere about Mersenne Twister. What I'm interested in is why there wouldn't be greater variation in the results from JavaScript's built-in Math.random function. Thanks!

+2  A: 

Looks perfectly random to me! (Hint: It's browser dependent.)

Personally, I think my implementation would be better, although I stole it off from XKCD, who should ALWAYS be acknowledged:

random = 4; // Chosen by a fair dice throw. Guaranteed to be random.
Arafangion
+1 for mentioning it's browser dependent, -1 for borrowing xkcd without linking.
Roger Pate
Required or not, since it's xkcd, it's getting attributed. :)
Arafangion
OT: I'm surprised and happy that "XKCD" was the answer to a University Challenge question this week :D
Matt Sach
+13  A: 

Your results are actually expected. If the random numbers are uniformly distributed in a range 1 to 10^n, then you would expect about 9/10 of the numbers to have n digits, and a further 9/100 to have n-1 digits.

jwoolard
Exactly. The distribution of the number of digits is expectedly going to be skewed. The distribution of the log of the number of digits shoudl be uniform however.
Noldorin
+2  A: 

If you use a number like 10000000000000000000 you're going beyond the accuracy of the datatype Javascript is using. Note that all the numbers generated end in "00".

Greg
That's not his problem in this case, though.
Joey
@Johannes - it's *one* of his problems :)
annakata
+24  A: 

Given numbers between 1 and 100.

  • 9 have 1 digit (1-9)
  • 90 have 2 digits (10-99)
  • 1 has 3 digits (100)

Given numbers between 1 and 1000.

  • 9 have 1 digit
  • 90 have 2 digits
  • 900 have 3 digits
  • 1 has 4 digits

and so on.

So if you select some at random, then that vast majority of selected numbers will have the same number of digits, because the vast majority of possible values have the same number of digits.

David Dorward
Your idea of randomness meaning perfectly and evenly distributed is intriguing...
Roger Pate
@R.Pate - random number *generation* isn't much use unless it is evenly distributed on a long scale
annakata
Read again. @David is only stating what kind of numbers there are between the limits, not the result of selecting N random numbers. I do admit the titling is misleading.
nikc
Edited. I phrased my initial answer ambiguously.
David Dorward
For the record, I voted up both this and @jwoolard's answers. I chose this one as the accepted answer because the examples make it clear as crystal why the distribution of numbers is skewed to numbers with more digits.
Andrew Hedges
@andrew-hedges quite right - this is the clearer answer, but thanks :)
jwoolard
+2  A: 

Well, if you are generating numbers up to, say, 1e6, you will hopefully get all numbers with approximately equal probability. That also means that you only have a one in ten chance of getting a number with one digit less. A one in a hundred chance of getting two digits less, etc. I doubt you will see much difference when using another RNG, because you have a uniform distribution across the numbers, not their logarithm.

Joey
+2  A: 
gargantaun
+4  A: 

There different types of randomness. Math.random gives you an uniform distribution of numbers. If you want different orders of magnitude, I would suggest using an exponential function to create what called a power law distribution:

Math.round(Math.exp(Math.random()*Math.log(maxmimum-minimum+1)))+minimum

should give you rougly the same number of 1-digit numbers as 2-digit numbers and as 3-digit numbers.

There are also other distributions for random numbers like the normal distribution (also called Gaussian distribution).

Christian
That's helpful, thanks!
Andrew Hedges
A: 

I ran this bit of code.

>>> d={};for (i=0;i<1000000;i++) { var s = getRandomInt(1,10000000000000000000).toString().length; if (d[s] == undefined) { d[s]=1; } else { d[s]++; } }; for (i in d) { console.log(i,d[i]); }

19 900261
18 89609
17 9156
16 869
15 95
14 9
12 1