[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
## Re: Normal distribution random numbers

**From**: |
tantalum |

**Subject**: |
Re: Normal distribution random numbers |

**Date**: |
Sun, 31 May 2020 15:12:16 +0000 |

**User-agent**: |
Posteo Webmail |

`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*))
~~~