9.1 Scalar Random Number Generators (.NET, C#, CSharp, VB, Visual Basic, F#)
NMath provides scalar generator classes that return random deviates from a variety of probability distributions.
Class |
Description |
Uniform distribution. |
|
Beta distribution. |
|
Binomial distribution. |
|
Exponential distribution. |
|
Gamma distribution. |
|
Geometric distribution. |
|
Johnson distribution. |
|
Log-normal distribution. |
|
Normal distribution. |
|
Pareto distribution. |
|
Poisson distribution. |
|
Triangular distribution. |
|
Weibull distribution. |
All NMath scalar random number generators, regardless of the distribution, require an underlying uniform random number generator that returns random deviates in the range zero to one. Each generator first generates a random uniform deviate in the range zero to one, then from this deviate derives a random number from the appropriate probability distribution. Thus, the statistical properties and performance of the generators largely depend on the statistical properties and performance of the underlying random number generator.
By default, all scalar generators use the NMath class RandGenMTwist as the underlying uniform generator. RandGenMTwist implements the Mersenne Twister algorithm, developed by Makoto Matsumoto and Takuji Nishimura in 1996-1997. This algorithm is faster and more efficient, and has a far longer period and far higher order of equidistribution, than other existing generators.
If you have your own uniform random number generator that you wish to use, all NMath random number generators provide constructor overloads that accept a RandomNumberGenerator.UniformRandomNumber function delegate. The function must generate uniform deviates in the range zero to one, and return a double.
For example, this code creates a delegate object from the method System.Random.NextDouble(), then constructs a binomial random number generator that uses this delegate:
Code Example – C# random number generators
var sysRand = new Random();
var uniformDeviates =
new RandomNumberGenerator.UniformRandomNumber(
sysRand.NextDouble );
int trials = 2000;
double prob = .002;
var binRand =
new RandGenBinomial( trials, prob, uniformDeviates );
Code Example – VB random number generators
Dim SysRand As New Random()
Dim UniformDeviates As New
RandomNumberGenerator.UniformRandomNumber(
AddressOf SysRand.NextDouble)
Dim Trials As Integer = 2000
Dim Prob As Double = 0.002
Dim BinRand As New RandGenBinomial(Trials, Prob, UniformDeviates)
All generators inherit a UniformDeviateMethod property from RandNumberGenerator for accessing and modify the underlying delegate method. For example, this code changes the delegate used by binRand:
Code Example – C# random number generators
var mt = new RandGenMTwist( );
binRand.UniformDeviateMethod =
new RandomNumberGenerator.UniformRandomNumber( mt.NextDouble );
Code Example – VB random number generators
Dim MT As New RandGenMTwist()
BinRand.UniformDeviateMethod =
New RandomNumberGenerator.UniformRandomNumber(AddressOf
MT.NextDouble)
All NMath generators provide a Next() method that returns a random deviate as a double, except for RandGenBinomial and RandGenPoisson that return an int. For example, this code prints out 100 random deviates from a normal distribution with mean of -12.9 and variance of 2.066:
Code Example – C# random number generators
double mean = -12.9;
double variance = 2.066;
var gen = new RandGenNormal( mean, variance );
for (int i=0; i<100; i++)
{
Console.WriteLine( gen.Next() );
}
Code Example – VB random number generators
Dim Mean As Double = -12.9
Dim Variance As Double = 2.066
Dim Gen As New RandGenNormal(Mean, Variance)
For I As Integer = 0 To 99
Console.WriteLine(Gen.Next())
Next
The base class RandomNumberGenerator also provides the abstract method NextDouble(), which is equivalent to calling Next(). This is a common method for applications that require polymorphic random number generation across the different generators, but also incurs the extra overhead of a virtual function call.
The Fill() method enables you to fill an array of float, double, FloatComplex, or DoubleComplex with random values. Thus:
Code Example – C# random number generators
var array1 = new double[ 100 ];
var array2 = new FloatComplex[ 100 ];
var gen = new RandGenPoisson();
gen.Fill( array1 );
gen.Fill( array2 );
Code Example – VB random number generators
Dim Array1(100) As Double
Dim Array2(100) As FloatComplex
Dim Gen As New RandGenPoisson()
Gen.Fill(Array1)
Gen.Fill(Array2)
Lastly, as a convenience, NMath vector and matrix classes provide constructor overloads that initialize all elements with random values. For example:
Code Example – C# random number generators
var gen = new RandGenUniform( 0, 100 );
var v = new DoubleVector( 10, gen );
var A = new DoubleComplexMatrix( 25, 25, gen );
Code Example – VB random number generators
Dim Gen As New RandGenUniform(0, 100)
Dim V As New DoubleVector(10, Gen)
Dim A As New DoubleComplexMatrix(25, 25, Gen)
As described above, all NMath random number generators, regardless of the distribution, use an underlying uniform random number generator to generate random deviates in the range (0,1), then derive from the deviate a random number from the appropriate probability distribution. Thus, the seed that determines the pseudorandom sequence is associated with the underlying uniform generator, not with the wrapping generator.
All NMath random number generator classes have Reset() and Reset(int) methods that attempt to reset the underlying uniform generator with the time of day, for the no argument reset, or the given seed, for the integer argument version. These methods return true if the reset was successful and false if it was not. The reset methods succeed if the following conditions are met:
1. The uniform generator delegate is an instance method; that is, the Target property of the Delegate class returns a non-null reference.
2. The object reference thus obtained has a method named Initialize() that returns void and takes no arguments, for the Reset() method, or a single integer argument for the Reset(int) method.
For example, this code attempts to generate two identical sequences by explicitly setting and resetting the seed:
Code Example – C# random number generators
int seed = 0x124;
var mt = new RandGenMTwist( seed );
var uniformDeviates =
new RandomNumberGenerator.UniformRandomNumber( mt.NextDouble );
var gen = new RandGenNormal( 50, 5, uniformDeviates );
var randomSequence1 = new DoubleVector( 100, gen );
if ( gen.Reset(seed) ) {
var randomSequence2 = new DoubleVector( 100, gen );
}
else {
Console.WriteLine( "Could not reset generator" );
}
Code Example – VB random number generators
Dim Seed As Integer = &H124
Dim MT As New RandGenMTwist(Seed)
Dim UniformDeviates As New
RandomNumberGenerator.UniformRandomNumber(AddressOf MT.NextDouble)
Dim Gen As New RandGenNormal(50, 5, UniformDeviates)
Dim RandomSequence1 As New DoubleVector(100, Gen)
If Gen.Reset(Seed) Then
Dim RandomSequence2 As New DoubleVector(100, Gen)
Else
Console.WriteLine("Could not reset generator")
End If