Previous: , Up: random prng   [Index]


49.2.5 Generating real numbers

We want a sample X from the discrete range of representable flonums in 0 <= X < 1 with a distribution that mimics the uniform distribution of real numbers R in the continuous range 0 < R < 1.

Knowing that the integers N generated by a PRNG are uniformly distributed in the range 0 <= N < M, a pseudo–random flonum X in the range 0 < X < 1 can be computed from a generated N with the following normalisation formula:

X = (1 + N) / (1 + M)

notice that:

N = 0        =>  X = 1 / (1 + M) > 0
N = (M - 1)  =>  X = M / (1 + M) < 1

sometimes this is enough, but we have to notice that: There may be more representable flonums in 0 < X < 1 than exact fractions like (1 + N) / (1 + M).

The following program prints the generated inexact fractions for the very simple case M = 5, it prints also the intervals between two adjacent fractions:

(import (rnrs)
  (vicare lists))

(define M 5)
(fold-left (lambda (prev-X X)
             (write (list X (- X prev-X)))
             (newline)
             X)
           0.0
           (map (lambda (N)
                  (inexact (/ (+ 1 N) (+ 1 M))))
             (list-tabulate M values)))
-| (0.16666666666666666 0.16666666666666666)
-| (0.3333333333333333  0.16666666666666666)
-| (0.5                 0.16666666666666669)
-| (0.6666666666666666  0.16666666666666663)
-| (0.8333333333333334  0.16666666666666674)

so the generated flonums are in “units” of approximately 1/6 = 0.166666666666666; we can compute this unit with 1 / (1 + M).

It is useful to be able to generate flonums in smaller units: We can do it by generating a pseudo–random integer N' uniformly distributed in a range larger than 0 <= N < M. We use the same method previously outlined for large integers generation. Generating integers in a specified range

So, we select a value for the desired unit, then we find M' such that:

1 / (1 + M') <= unit
=>  1 + M' >= 1 / unit
=>  M' >= (1 / unit) - 1
=>  1  >= (1 / unit) - 1 / M'

then we generate a big pseudo–random integer N' in the range 0 <= N' < M' and normalise it with:

X = (1 + N') / (1 + M')

Previous: , Up: random prng   [Index]