Previous: random prng integers, Up: random prng [Index]
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: random prng integers, Up: random prng [Index]