How random is C#’s random generator? Have you ever thought about this?
This article might be a bit long; so the summary is, C#’s random generator produces a fairly uniform distribution. The smaller the range, and the larger the number of iterations, the more uniform (eg. variance decreases from 20% to 0.6%).
Let’s go back to the basics. What is random? Random can mean “a uniform distribution,” meaning if I ask for ten random numbers in the range [1, 10], I expect each number to show up about once, i.e. all options are equally likely to appear, and appear approximately equally. Here’s what a uniform distribution looks like:
Contrast this to a “normal distribution,” also known as a “bell curve.” This is something that occurs naturally in a lot of domains (eg. human height, human weight). Here’s what it looks like:
Back to Random for a minute — the problem with computers is that computers are inherently deterministic and non-random. So instead of coming up with a truly random generator, we have to settle for these so-called “psuedo random number generators” (PRNGs), which are the best randomization we can make in a deterministic world.
The problem with psuedo-random number generators, is that they’re “psuedo” — they’re not really random. This can have dire implications in security, where cryptography relies on random number generation. If you could predict the next series of random numbers, you could potentially crack the encryption! For this reason, so-called “cryptographically-secure PRNGs” exist, which satisfy some rigorous standard of being “random enough” for cryptography. Phew!
In fact, if you want real random, you can check out the HotBits website, which uses an actual, real and real-world random distribution (radioactive decay) to generate random numbers. Very cool.
So, how random is the C# built-in Random class? Let’s take a look. To test this out, I created a small script to generate random numbers from 0 to 99, and to query the random generator 100 * 100 times; this means we can interpret the results as a percentage — if every number occurs roughly 100 times, then it’s uniform; more and less than that is our variance.
Here are what the results looked like:
The results don’t look bad — the distribution is fairly even. You’ll notice that the range of numbers is +-20, which is approximately a 20% margin of error.
Two interesting observations:
- Smaller Range: A smaller range of numbers (eg. 1-10 instead of 1-100) produces less variation and a more uniform distribution.
- More Iterations: We perform 100*100 iterations; if we performed, say, 100*10000 iterations, we would see less variation.
So is the built-in random number generator “good enough?” Unless you’re building some hardcore security algorithm, the answer is probably “yes.” (And if you’re doing that, there are one or two cryptographically-secure random number generators in the System.Cryptography namespace.)
I would recommend that you try to use a smaller range of numbers if possible, if you really care about a uniform distribution.
Other than that … you can sum up the article as “yes, it really is random!”