[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Normal distribution random numbers
From: |
Zelphir Kaltstahl |
Subject: |
Re: Normal distribution random numbers |
Date: |
Sun, 31 May 2020 21:54:27 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Icedove/60.9.0 |
Hi!
Interesting technique, that when thinking about it, intuitively makes
sense to me. Thanks for sharing!
Regards,
Zelphir
On 31.05.20 17:12, tantalum wrote:
> surely not the ideal way to generate numbers with a normal
> distribution, but there is a way to use custom probabilities from a
> list, which i think is nice to know.
> it works like this:
>
> have a list of probabilities. can be as long as you want. i think that
> is called probability density.
> ->
> (1 0 3 1)
>
> create the cumulative sums for this list. that is, sums like this
> (a b c ...) -> (a (+ a b) (+ a b c) ...)
> i think that is called cumulative distribution.
> ->
> (1 1 4 5)
>
> create a random number up to the largest sum
> ->
> (random 5)
>
> return the first index of the list of cumulative sums that is greater
> than the random number.
> given the distribution above, you would see index 2 a lot, never index
> 1, and index 0 and 3 rarely.
>
> ~~~
> (use-modules ((srfi srfi-1) #:select (last)))
>
> (define (cusum a . b)
> "calculate cumulative sums from the given numbers.
> (a b c ...) -> (a (+ a b) (+ a b c) ...)"
> (cons a (if (null? b) (list) (apply cusum (+ a (car b)) (cdr b)))))
>
> (define* (random-discrete-f probabilities #:optional (state
> *random-state*))
> "(real ...) [random-state] -> procedure:{-> integer}"
> (let* ((cuprob (apply cusum probabilities)) (sum (last cuprob)))
> (lambda ()
> (let ((deviate (random sum state)))
> (let loop ((a 0) (b cuprob))
> (if (null? b) a (if (< deviate (car b)) a (loop (+ 1 a) (cdr
> b)))))))))
>
> (define random* (random-discrete-f (list 1 0 3 1)
> (random-state-from-platform)))
> (display (random*))
> ~~~
>
>