Introduction
The Mersenne Twister (MT) is a pseudorandom number generator (PRNG) developed by Makoto Matsumoto and Takuji Nishimura[1][2] during 1996-1997. MT has the following merits:
- It is designed with consideration on the flaws of various existing generators.
- Far longer period and far higher order of equidistribution than any other implemented generators. (It has been proven that the period is 2^19937-1 and 623-dimensional equidistribution property is assured.)
- Fast generation. (Although it depends on the system, it is reported that MT is sometimes faster than the standard ANSI-C library in a system with pipeline and cache memory.)
- Efficient use of the memory.
Credit where it's due
I present a C# class (RandomMT
) that encapsulates the work of the creators. I do not take credit for their work; I am merely presenting an object oriented (OO) version of their code that you can simply drop into your game or application. This work has also been derived from CRandomMT
. CRandomMT
is a C++ wrapper class for the Mersenne Twister, the original Code Project article can be found here. In that article I not only presented a wrapper class for this marvelous pseudorandom number generator but I also discussed the equidistribution of the MT algorithm as well as its speed increases. I will refer you to those articles for the time being as I do not have access to the latest version of TrueTime
.
RandomMT
The inspiration for developing a C# version of this class was two-fold.
- I wanted to learn C# and what better way to learn a new language than by converting code that you are familiar with and
- I�ve been thinking more and more about the future of game development for the PC � specifically using a .NET language.
This thinking resulted in me writing a document that is as much hypothetical as it is factual with respect to game development for the PC in the coming years, those who are interested can find that article here.
Class description
RandomMT::RandomMT()
This is the default CTOR.
RandomMT::RandomMT(ULONG seed)
A constructor that you provide the seed value.
RandomMT::~RandomMT()
The DTOR.
RandomMT::SeedMT()
Used to seed or re-seed the random number generator.
ULONG RandomMT::RandomInt()
Returns an unsigned long
random number.
int RandomMT::RandomRange(int hi, int lo)
Returns an int
random number falling in the range specified.
int RandomMT::RollDice(int face, int number_of_dice)
Returns an int
random number for the number of dice specified and the face of the die.
int RandomMT::D#(int die_count)
Returns a simulated roll of the number of dice specified for the die (determined by #). These are just wrappers around RollDice()
int RandomMT::HeadsOrTails()
Returns 0 or 1, used to simulate a coin flip.
Example usage
namespace MersenneTwister
.
.
.
RandomMT random = new RandomMT();
int rand_3d6 = random.D6(3);
.
.
.
Notes about this implementation
I have held closely to my original C++ implementation as much as possible. The original code used pointer arithmetic which you cannot do in C# and keep the code managed (per MSDN). If someone knows a better approach to this, feel free to let me know.
Update: MT19937
I have updated the code to use the most recent version of the algorithm, MT19937.
Class description
Here is a brief overview of the MT19937 version of the class.
ulong genrand_int32()
generates a random number on [0,0xffffffff]-interval
long genrand_int31()
generates a random number on [0,0x7FFFFFFF]-interval
double genrand_real1()
generates a random number on [0,1]-real-interval
double genrand_real2()
generates a random number on [0,1]-real-interval
double genrand_real3()
generates a random number on [0,1]-real-interval
double genrand_real53()
generates a random number on [0,1] with 53 bit resolution
int RandomRange(int lo, int hi)
returns a random number in the range [hi-lo+1]
Usage
namespace MersenneTwister
.
.
.
MT19937 random = new MT19937();
int rand_d6 = random.RandomRange(1,6);
.
.
.
About the demo application
Again, the demo application is fairly lame. This application allows you to roll six 6 sided die and it keeps track of the total number of times that a number has �hit� � you can roll once or 1000 times.
I�ve made use of GDI+ and as I said, I�m learning C# as well as the .NET framework so I may have misused or abused much of GDI+ functionality.
Conclusion
The pursuit of the perfect PRNG is an ongoing effort that eludes computer scientists and mathematicians alike. The Mersenne Twister is generally considered to be fast, small and provides equal distribution. C# is an exciting language and I am looking forward to learning and coding with it in the coming future.
Thanks
Thanks go out to Makoto Matsumoto and Takuji Nishimura for creating the algorithm.
References
- [1] "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator", M. Matsumoto and T. Nishimura, ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3--30.
- [2] Mersenne Twister: A random number generator