On 14.12.2008, at 08:19, Mark H. wrote:

> So I'm going to stop pretending like I'm an expert and actually post
> some Clojure code.  Be constructively critical 'cause I'm a n00b in
> that regard ;-)  This is a pseudorandom number generator for the
> Gaussian (0,1) distribution.

...

Isn't that the standard Box-Muller transform?

Anyway, I tried to rewrite your code into a function that takes an  
input stream of uniformly distributed random numbers and transforms  
it into a stream of Gaussian random numbers. The advantage is that  
there is no need to keep track explicitly of the state of the  
calculation. In the following, I construct my input stream by  
repeatedly calling Clojure's (rand), but you could easily substitute  
any other source, including java.Util.Random.

Konrad.



(defn rng-uniform
   "Return an infinite lazy sequence of random numbers"
   []
   (drop 1 (iterate (fn [_] (rand)) nil)))

(defn transform-to-gaussian
   "Transform a sequence of uniform random number in the interval [0, 1)
    into a sequence of Gaussian random numbers."
   [uniform-seq]
   (let [[U1 U2 & uniform-rest] uniform-seq
        V1 (- (* 2.0 U1) 1.0)
        V2 (- (* 2.0 U2) 1.0)
        S  (+ (* V1 V1) (* V2 V2))
        LS (. Math sqrt (/ (* -2.0 (. Math log S)) S))
        X1 (* V1 LS)
        X2 (* V2 LS)]
     (if (or (>= S 1) (= S 0))
       (recur uniform-rest)
       (lazy-cons X1 (lazy-cons X2 (transform-to-gaussian uniform- 
rest))))))

; Get 10 Gaussian random numbers
(take 10 (rng-gaussian))


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to