Instead of producing a series of numbers distributed uniformly over an interval, we need data following one of the classical distributions such as the normal distribution (i.e. the numbers should give a "bell curve").

The easy solution is use the "random.plt" library from PLaneT.

Let's try generating numbers with a Gaussian distribution (a normal distribution with mean 0 and standard deviance 1):

> (require (planet "random.ss" ("schematics" "random.plt" 1 0))) > (random-gaussian) 0.7386912134436788 > (random-gaussian) -0.4388994504610697

If we want to mimick a stocastic variable, we can use `random-source-make-gaussians`

and
a source of random bits.

> (define X (random-source-make-gaussians default-random-source)) > (X) 0.5826066449247809 > (X) 0.7865269446783535

Alternatively, one could simple define `X`

as

> (define X (lambda () (random-gaussian)))

Given a distribution, lookup an algorithm in a statistics reference. If you can't find an algorithm, consult a numerical analyst.

Let's examine the case of the normal distribution. The two parameters `mu`

(mean)
and `sigma`

(standard deviance) determines a specific normal distribution.

; derived from example in the documentation of SRFI27 (require (lib "27.ss" "srfi")) (define (make-normal-distributed-variable mu sigma) (let ((mu (* 1.0 mu)) (sigma (* 1.0 sigma)) (next #f)) (lambda () (cond (next (let ((result next)) (set! next #f) (+ mu (* sigma result)))) (else (let loop () (let* ((v1 (- (* 2.0 (random-real)) 1.0)) (v2 (- (* 2.0 (random-real)) 1.0)) (s (+ (* v1 v1) (* v2 v2)))) (cond ((>= s 1.0) (loop)) (else (let ((scale (sqrt (/ (* -2.0 (log s)) s)))) (set! next (* scale v2)) (+ mu (* sigma scale v1))))))))))))

An example of usage:

> (define X (make-normal-distributed-variable 0 1)) > (X) 0.7386912134436788 > (X) -0.4388994504610697 > (X) 0.5826066449247809

If you are unsatisfied with the fact that you get the exact same numbers as above, then randomize the source of random numbers:

> (random-source-randomize! default-random-source)

The algorithm used is the polar Box Muller method. The algorithm takes two independent uniformly distributed random numbers between 0 and 1 (represented in the code as `(random-real)`

) and generates two numbers with a mean of my and standard deviation sigma. The method produces two numbers at a time, so since we only need one, the second is saved for later in the variable `next`

.

Note that the Perl Cookbook includes an interesting discussion of converting a set of values (and weights) into a distribution. This should also be converted to Scheme and shown here.

Mathematically-inclined Schemers should also take a good look at random.ss, which contains these and many other statistical methods.

It's also worth noting that if a bell-curve type thing is all you're looking for, generating two or more random numbers and taking the average will tend to favor the middle values. For example, consider a pair of dice: there is exactly one combination out of 36 that yields 2 and one that yields 12 (the outlying values), while there are six combinations that yield 7 (the center value). You could also use a weighed average to reduce the effect if averaging two random numbers produces a bell curve which is too steep for your application.

-- BrentAFulgham - 14 May 2004

-- JensAxelSoegaard - 01 Jun 2004 -- JensAxelSoegaard - 12 Dec 2006

[TODO: Move the following remarks to another recipe]

If you wish to randomly select from a set of weights and values, convert the weights into a probability distribution, then use the resulting distribution to pick a value.

If you have a list of weights and values you want to randomly pick from, follow this two-step process: First, turn the weights into a probability distribution with weight_to_dist below, and then use the distribution to randomly pick a value with weighted_rand:

[TODO: Use the random-source-make-discretes from random.ss to solve the above problem]

CookbookForm | |
---|---|

TopicType: | Recipe |

ParentTopic: | NumberRecipes |

TopicOrder: | 100 |

The copyright for certain compilations of material taken from this website is held by the SchematicsEditorsGroup - see ContributorAgreement & LGPL.

Other than such compilations, this material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.

Ideas, requests, problems regarding Schematics Cookbook? Send feedback. / You are Main.guest