2 people like it.

Simple normally distributed random number generator

There are better (faster, more efficient) ways to do this, F# numerics library for a start, but this is at least interesting. This snippet uses the polar form of the Box-Muller method to generate Normal- (Gaussian-) distributed random numbers as an infinite sequence. The polar form is more efficient than the basic form as it does not rely on trigonometric function calls, but there are far more efficient alogrithms (read harder to implement) e.g. the Ziggurat method (for a later post).

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
let normalDistRandom mean stdDev = 
    let rand = new System.Random()
    let rec polarBoxMullerDist () = seq {
            let rec getRands () =
                let u = (2.0 * rand.NextDouble()) - 1.0
                let v = (2.0 * rand.NextDouble()) - 1.0
                let w = u * u + v * v
                if w >= 1.0 then
                    getRands()
                else
                    u, v, w
            let u, v, w = getRands()
            
            let scale = System.Math.Sqrt(-2.0 * System.Math.Log(w) / w)
            let x = scale * u
            let y = scale * v
            yield mean + (x * stdDev); yield mean + (y * stdDev); yield! polarBoxMullerDist ()
        }
    polarBoxMullerDist ()
val normalDistRandom : mean:float -> stdDev:float -> seq<float>

Full name: Script.normalDistRandom
val mean : float
val stdDev : float
val rand : System.Random
namespace System
Multiple items
type Random =
  new : unit -> Random + 1 overload
  member Next : unit -> int + 2 overloads
  member NextBytes : buffer:byte[] -> unit
  member NextDouble : unit -> float

Full name: System.Random

--------------------
System.Random() : unit
System.Random(Seed: int) : unit
val polarBoxMullerDist : (unit -> seq<float>)
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val getRands : (unit -> float * float * float)
val u : float
System.Random.NextDouble() : float
val v : float
val w : float
val scale : float
type Math =
  static val PI : float
  static val E : float
  static member Abs : value:sbyte -> sbyte + 6 overloads
  static member Acos : d:float -> float
  static member Asin : d:float -> float
  static member Atan : d:float -> float
  static member Atan2 : y:float * x:float -> float
  static member BigMul : a:int * b:int -> int64
  static member Ceiling : d:decimal -> decimal + 1 overload
  static member Cos : d:float -> float
  ...

Full name: System.Math
System.Math.Sqrt(d: float) : float
System.Math.Log(d: float) : float
System.Math.Log(a: float, newBase: float) : float
val x : float
val y : float
Raw view Test code New version

More information

Link:http://fssnip.net/o7
Posted:10 years ago
Author:Kevin Roche
Tags: randon number generation , statistics , gaussian distribution , normal distribution , infinite sequence