RandomLib  1.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
Random real numbers
Back to Random integers. Forward to Other random results. Up to Contents.

The Random class generates two classes of uniform real results: fixed point numbers (where the spacing between possible results is a constant) and floating point numbers (where the spacing between possible results varies).

Fixed-point real numbers

The results returned by Fixed(), FixedU(), FixedN(), FixedW(), FixedO(), and FixedC() are "fixed-point reals" with precision p. These are of the form i / 2p where i is an integer. If, for real data type RealType, we restrict p > 0 and p ≤ std::numeric_limits<RealType>::digits, then all such numbers in [-1,1] are representable. For p = 3, the set of numbers in [0,1] is {0, 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, 1}.

The results returned FixedS() are of "offset fixed-point reals" with precision p. These are of the form (i + 1/2) / 2p where i is an integer. If, for real data type RealType, we restrict p > 0 and p ≤ std::numeric_limits<RealType>::digits, then all such numbers in (−1/2,1/2) are representable. (This only "works" for radix 2 systems; with larger bases, the results can't be represented exactly.) Note that possibly "exceptional" numbers, −1/2, 0, and 1/2, are not included in this set. For p = 3, the set of numbers in (−1/2,1/2) is {−7/16, −5/16, −3/16, −1/16, 1/16, 3/16, 5/16, 7/16}.

Floating-point real numbers

The results returned by Float(), FloatU(), FloatN(), FloatW() are "floating-point reals" with precision p and exponent range e. The possible results for such floating numbers in [−1,1] consist of

For real data type RealType, such numbers are representable if

For e = 0, the numbers become the fixed point numbers with precision p.

Here is an example of the floating point points with p = 3 and e = 2 together with the probabilities yielded by Float(), FloatU(), FloatN().

Floats with p = 3, e = 2
X prob(Float() = X) prob(FloatU() = X) prob(FloatN() = X)
0 1/32 0 0.5/32
1/321/32 1/32 1/32
2/321/32 1/32 1/32
3/321/32 1/32 1/32
4/321/32 1/32 1/32
5/321/32 1/32 1/32
6/321/32 1/32 1/32
7/321/32 1/32 1/32
4/161/16 1/32 1.5/32
5/161/16 1/16 1/16
6/161/16 1/16 1/16
7/161/16 1/16 1/16
4/8 1/8 1/16 1.5/16
5/8 1/8 1/8 1/8
6/8 1/8 1/8 1/8
7/8 1/8 1/8 1/8
1 0 1/8 0.5/8

The description of floating-point numbers assumes that the underlying hardware supports denormalized numbers. This is the case with most modern computers. The code attempts to deal also with older hardware where there's a gap between 0 and 1/2e + 1, but this has not been tested.

Summary of real number routines

The following table provides a succinct definition of each of the member functions of Random routines that return a real result. Here u is a uniformly distributed random number in (0,1). This is drawn from a continuous distribution; i.e., it may be thought of as consisting of a binary point followed by an infinite sequence of random binary bits. (This is just a useful conceptual framework. None of the implementations of these functions require an explicit realization of u.)

The term "fixed" means a fixed-point real with precision p, and we have h = 1/2p (the smallest positive fixed-point number). The term "float" means a floating-point real with precision p and exponent range e.

Definitions of routines returning reals
routine mnemonic definition
Fixed() default (down) round u down to previous fixed
FixedU() upper round u up to next fixed
FixedN() nearest round u to nearest fixed
FixedW() wide round 2u − 1 to nearest fixed
FixedS() symmetric round u − 1/2 to nearest offset fixed
FixedO() open round (1 − h)u up to nearest fixed
FixedC() closed round (1 + h)u down to nearest fixed
Float() default (down) round u down to previous float
FloatU() upper round u up to next float
FloatN() nearest round u to nearest float
FloatW() wide round 2u − 1 to nearest float

The precision and exponent range are determined as follows. Each of the fixed-point routines comes in 3 variants, for example,

Similarly each of the floating-point routines comes in 3 variants, for example,

Typical values of digits and min_exponent are given by

Typical parameters for real types
type digits -min_exponent
float 24 125
double 53 1021
long double 64 16381
long double (Power PC)106968
long double (Sun)113 16494

In the following tables, the columns have the following meanings

next(X) is the next representable float following X. prev(X) is the previous representable float preceding X.

Properties of routines returning reals
routine min max num prob
Fixed() 0 1−h 2p h
FixedU() h 1 2p h
FixedN() 0 1 2p + 1 h (h/2 at endpoints)
FixedW() −1 1 2p+1 + 1 h/2 (h/4 at endpoints)
FixedS() −(1−h)/2 (1−h)/2 2p h
FixedO() h 1−h 2p−1 h/(1−h)
FixedC() 0 1 2p+1 h/(1+h)
Float() 0 1−h 2p(1+e/2) min(1,next(X))−X
FloatU() 1/2p+e 1 2p(1+e/2) X−max(0,prev(X))
FloatN() 0 1 2p(1+e/2)+1 (min(1,next(X))−max(0,prev(X)))/2
FloatW() −1 1 2p+1(1+e/2)+1 (min(1,next(X))−max(−1,prev(X)))/4

From these definitions, we can show that:

We can easily show that certain distributions are equivalent:

Equivalences between routines returning reals
Function Equivalent
FixedU<RealType,p>() Fixed<RealType,p>() + h
FixedU<RealType,p>() 1 − Fixed<RealType,p>()
FixedN<RealType,p>() Boolean() ? Fixed<RealType,p>() : FixedU<RealType,p>()
FixedN<RealType,p>() 1 − FixedN<RealType,p>()
FixedO<RealType,p>() 1 − FixedO<RealType,p>()
FixedC<RealType,p>() 1 − FixedC<RealType,p>()
FixedS<RealType,p>() Fixed<RealType,p>() − (1−h)/2
FixedS<RealType,p>() − FixedS<RealType,p>()
FixedW<RealType,p>() (Boolean() ? 1 : −1) FixedN<RealType,p>()
FixedW<RealType,p>() − FixedW<RealType,p>()
FixedW<RealType,p−1>() 2 FixedN<RealType,p>() − 1
FloatN<RealType,p,e>() Boolean() ? Float<RealType,p,e>() : FloatU<RealType,p,e>()
FloatW<RealType,p,e>() (Boolean() ? 1 : −1) FloatN<RealType,p,e>()
FloatW<RealType,p,e>() − FloatW<RealType,p,e>()
Float<RealType,p,0>() Fixed<RealType,p>()
FloatU<RealType,p,0>() FixedU<RealType,p>()
FloatN<RealType,p,0>() FixedN<RealType,p>()
FloatW<RealType,p,0>() FixedW<RealType,p>()

A caution about FixedO() and FixedC(). All four of FixedS(), FixedN() − 0.5, FixedO() − 0.5, and FixedC() − 0.5 produce results which are strictly symmetric about 0 and would thus be suitable for an unbiased random walk. The variances of the first two distributions are 1/12 + O(h2), close to the ideal value. On the other hand the variances of the distributions of FixedO() and FixedC() are 1/12 + O(h), significantly further from the ideal value. (In practice, using a strictly symmetric normal distribution is preferable for simulating a random walk.)

Similarly, consider estimating the value of π by randomly selecting points in a unit square and determining what fraction lie in a circle of diameter 1. Sampling in the square using FixedO() or FixedC() gives poorer results than FixedN(), and FixedS() gives slightly better results.

Because of their definitions in terms of u, any of Fixed(), FixedU(), FixedN(), or FixedS() can be used to cover the periodic unit interval in an unbiased way. Thus to sample an angle uniformly, use 2 * π * Fixed() or 2 * π * FixedS(). The latter has the advantage that it is strictly symmetric about zero. In addition, angles which are multiples of π/2 are avoided (which may obviate the need to check for special cases).

Usually, these real routines would be invoked by specifying the type and allowing the precision to be determined from the type, e.g., Real<double>(). However, in some cases it might be useful to specify a lower precision:

Back to Random integers. Forward to Other random results. Up to Contents.