The two classes RNG
and Random
are used together to
generate a variety of random number distributions. A distinction must
be made between random number generators, implemented by class
RNG
, and random number distributions. A random number
generator produces a series of randomly ordered bits. These bits can be
used directly, or cast to other representations, such as a floating
point value. A random number generator should produce a uniform
distribution. A random number distribution, on the other hand, uses the
randomly generated bits of a generator to produce numbers from a
distribution with specific properties. Each instance of Random
uses an instance of class RNG
to provide the raw, uniform
distribution used to produce the specific distribution. Several
instances of Random
classes can share the same instance of
RNG
, or each instance can use its own copy.
Random distributions are constructed from members of class RNG
,
the actual random number generators. The RNG
class contains no
data; it only serves to define the interface to random number
generators. The RNG::asLong
member returns an unsigned long
(typically 32 bits) of random bits. Applications that require a number
of random bits can use this directly. More often, these random bits are
transformed to a uniform random number:
// // Return random bits converted to either a float or a double // float asFloat(); double asDouble(); };
using either asFloat
or asDouble
. It is intended that
asFloat
and asDouble
return differing precisions;
typically, asDouble
will draw two random longwords and transform
them into a legal double
, while asFloat
will draw a single
longword and transform it into a legal float
. These members are
used by subclasses of the Random
class to implement a variety of
random number distributions.
Class ACG
is a variant of a Linear Congruential Generator
(Algorithm M) described in Knuth, Art of Computer Programming, Vol
III. This result is permuted with a Fibonacci Additive Congruential
Generator to get good independence between samples. This is a very high
quality random number generator, although it requires a fair amount of
memory for each instance of the generator.
The ACG::ACG
constructor takes two parameters: the seed and the
size. The seed is any number to be used as an initial seed. The
performance of the generator depends on having a distribution of bits
through the seed. If you choose a number in the range of 0 to 31, a
seed with more bits is chosen. Other values are deterministically
modified to give a better distribution of bits. This provides a good
random number generator while still allowing a sequence to be repeated
given the same initial seed.
The size
parameter determines the size of two tables used in the
generator. The first table is used in the Additive Generator; see the
algorithm in Knuth for more information. In general, this table is
size
longwords long. The default value, used in the algorithm in
Knuth, gives a table of 220 bytes. The table size affects the period of
the generators; smaller values give shorter periods and larger tables
give longer periods. The smallest table size is 7 longwords, and the
longest is 98 longwords. The size
parameter also determines the
size of the table used for the Linear Congruential Generator. This value
is chosen implicitly based on the size of the Additive Congruential
Generator table. It is two powers of two larger than the power of two
that is larger than size
. For example, if size
is 7, the
ACG table is 7 longwords and the LCG table is 128 longwords. Thus, the
default size (55) requires 55 + 256 longwords, or 1244 bytes. The
largest table requires 2440 bytes and the smallest table requires 100
bytes. Applications that require a large number of generators or
applications that aren't so fussy about the quality of the generator may
elect to use the MLCG
generator.
The MLCG
class implements a Multiplicative Linear
Congruential Generator. In particular, it is an implementation of the
double MLCG described in "Efficient and Portable Combined Random
Number Generators" by Pierre L'Ecuyer, appearing in
Communications of the ACM, Vol. 31. No. 6. This generator has a
fairly long period, and has been statistically analyzed to show that it
gives good inter-sample independence.
The MLCG::MLCG
constructor has two parameters, both of which are
seeds for the generator. As in the MLCG
generator, both seeds are
modified to give a "better" distribution of seed digits. Thus, you can
safely use values such as `0' or `1' for the seeds. The MLCG
generator used much less state than the ACG
generator; only two
longwords (8 bytes) are needed for each generator.
A random number generator may be declared by first declaring a
RNG
and then a Random
. For example, ACG gen(10, 20);
NegativeExpntl rnd (1.0, &gen);
declares an additive congruential
generator with seed 10 and table size 20, that is used to generate
exponentially distributed values with mean of 1.0.
The virtual member Random::operator()
is the common way of
extracting a random number from a particular distribution. The base
class, Random
does not implement operator()
. This is
performed by each of the subclasses. Thus, given the above declaration
of rnd
, new random values may be obtained via, for example,
double next_exp_rand = rnd();
Currently, the following subclasses
are provided.
The binomial distribution models successfully drawing items from
a pool. The first parameter to the constructor, n
, is the
number of items in the pool, and the second parameter, u
,
is the probability of each item being successfully drawn. The
member asDouble
returns the number of samples drawn from
the pool. Although it is not checked, it is assumed that
n>0
and 0 <= u <= 1
. The remaining members allow
you to read and set the parameters.
The Erlang
class implements an Erlang distribution with
mean mean
and variance variance
.
The Geometric
class implements a discrete geometric
distribution. The first parameter to the constructor,
mean
, is the mean of the distribution. Although it is not
checked, it is assumed that 0 <= mean <= 1
.
Geometric()
returns the number of uniform random samples
that were drawn before the sample was larger than mean
.
This quantity is always greater than zero.
The HyperGeometric
class implements the hypergeometric
distribution. The first parameter to the constructor,
mean
, is the mean and the second, variance
, is the
variance. The remaining members allow you to inspect and change
the mean and variance.
The NegativeExpntl
class implements the negative
exponential distribution. The first parameter to the constructor
is the mean. The remaining members allow you to inspect and
change the mean.
The Normal
class implements the normal distribution. The
first parameter to the constructor, mean
, is the mean and
the second, variance
, is the variance. The remaining
members allow you to inspect and change the mean and variance.
The LogNormal
class is a subclass of Normal
.
The LogNormal
class implements the logarithmic normal
distribution. The first parameter to the constructor,
mean
, is the mean and the second, variance
, is the
variance. The remaining members allow you to inspect and change
the mean and variance. The LogNormal
class is a subclass
of Normal
.
The Poisson
class implements the poisson distribution.
The first parameter to the constructor is the mean. The
remaining members allow you to inspect and change the mean.
The DiscreteUniform
class implements a uniform random variable over
the closed interval ranging from [low..high]
. The first parameter
to the constructor is low
, and the second is high
, although
the order of these may be reversed. The remaining members allow you to
inspect and change low
and high
.
The Uniform
class implements a uniform random variable over the
open interval ranging from [low..high)
. The first parameter to
the constructor is low
, and the second is high
, although
the order of these may be reversed. The remaining members allow you to
inspect and change low
and high
.
The Weibull
class implements a weibull distribution with
parameters alpha
and beta
. The first parameter to
the class constructor is alpha
, and the second parameter
is beta
. The remaining members allow you to inspect and
change alpha
and beta
.
The RandomInteger
class is not a subclass of Random,
but a stand-alone integer-oriented class that is dependent on the
RNG classes. RandomInteger returns random integers uniformly from
the closed interval [low..high]
. The first parameter to the
constructor is low
, and the second is high
, although
both are optional. The last argument is always a generator.
Additional members allow you to inspect and change low
and
high
. Random integers are generated using asInt()
or
asLong()
. Operator syntax (()
) is also available as a
shorthand for asLong()
. Because RandomInteger
is often
used in simulations for which uniform random integers are desired over
a variety of ranges, asLong()
and asInt
have high
as an optional argument. Using this optional argument produces a
single value from the new range, but does not change the default
range.