![]() |
General Programming »
Algorithms & Recipes »
General
Intermediate
License: The Code Project Open License (CPOL)
Simple Random Number GenerationBy John D. CookA simple random number generator in C# |
C#2.0, Windows, .NET2.0, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Random number generation is tricky business. Good random number generation algorithms are tricky to invent. Code implementing the algorithms is tricky to test. And code using random number generators is tricky to test. This article will describe SimpleRNG, a very simple random number generator. The generator uses a well-tested algorithm and is quite efficient. Because it is so simple, it is easy to drop into projects and easy to debug into.
SimpleRNG can be used to generate random unsigned integers and double values distributed uniformly, exponentially, or normally.
For many applications, it hardly matters what random number generator you use, and the one included in the .NET runtime would be the most convenient. However, sometimes it helps to have your own random number generator. Here are some examples.
George Marsaglia is one of the leading experts in random number generation. He's come up with some simple algorithms that nevertheless produce high quality output. The generator presented here, SimpleRNG, uses Marsaglia's MWC (multiply with carry) algorithm. The algorithm is mysterious but very succinct. The algorithm passes Marsaglia's DIEHARD battery of tests, the acid test suite for random number generators.
The heart of SimpleRNG is three lines of code. Here is the method that generates uniformly distributed unsigned integers.
private static uint GetUint()
{
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
Here m_w and m_z are unsigned integers, the only member variables of the class. It's not at all obvious why this code should produce quality random numbers, but it does.
The unsigned integer is then turned into a double in the open interval (0, 1). ("Open" means that the end points are not included; the method will not return 0 or 1, only numbers in between.)
public static double GetUniform()
{
// 0 <= u <= 2^32
uint u = GetUint();
// The magic number below is 1/(2^32 + 2).
// The result is strictly between 0 and 1.
return (u + 1) * 2.328306435454494e-10;
}
The SimpleRNG class has two seeds. These have default values, or they can be specified by calling SetSeed() with one or two arguments. These arguments must be non-zero; if an argument is zero, it is replaced by the default value. Some may prefer to throw an exception in this case rather than silently fix the problem. There is also an option to set the seed values from the system clock using SetSeedFromSystemTime(). Once the class is initialized, there is only one public method to call, GetUniform().
The code to test SimpleRNG is more complicated than SimpleRNG itself. The test code included as a demo uses a statistical test, the Kolmogorov-Smirnov test, to confirm that the output of the generator has the expected statistical properties. If this test were applied repeatedly with ideal random input, the test would fail on average once in every thousand applications. This is highly unusual in software testing: the test should fail occasionally! That's statistics for you. Don't be alarmed if the test fails. Try again with another seed and it will most likely pass. The test is good enough to catch most coding errors since a bug would likely result in the test failing far more often.
For more information on random number generation, particularly on subtle things that can go wrong, see the CodeProject article Pitfalls in Random Number Generation. If you are using C++, see Random number generation using C++ TR1.
GetUniform cannot return 0.
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 23 Oct 2008 Editor: Sean Ewington |
Copyright 2008 by John D. Cook Everything else Copyright © CodeProject, 1999-2010 Web09 | Advertise on the Code Project |