Necesitando un generador de números aleatorios que produce una muestra de una distribución normal (gaussiana), me he portado a F # una parte de John D. Cook's C# generator:Hilo de seguridad en F #
let mutable m_w = 521288629u
let mutable m_z = 362436069u
let private getUint() =
m_z <- 36969u * (m_z &&& 65535u) + (m_z >>> 16)
m_w <- 18000u * (m_w &&& 65535u) + (m_w >>> 16)
(m_z <<< 16) + m_w
let private setSeed() =
let dt = System.DateTime.Now
let x = dt.ToFileTime()
m_w <- uint32 (x >>> 16)
m_z <- uint32 (x % 4294967296L)
let private getUniform() =
let u = getUint()
(float u + 1.) * 2.328306435454494e-10
let private randomNormal() =
let u1 = getUniform()
let u2 = getUniform()
let r = sqrt (-2. * (log u1))
let theta = 2. * System.Math.PI * u2
r * sin (theta)
/// Returns a normal (Gaussian) random sample with mean 0 and standard deviation 1
let randn() =
setSeed()
randomNormal()
/// Returns an array of normal (Gaussian) random samples
let randns n m =
setSeed()
[| for i in 0 .. n - 1 -> randomNormal() |]
Esta implementación obras bien, pero no es seguro para subprocesos. Dado que el código que depende de él hace un uso extensivo de la Biblioteca de subprocesos paralelos, necesito que sea seguro para subprocesos.
Esto no me parece obvio porque en el núcleo del método se encuentran dos miembros mutables que son bastante indispensables. ¿Hay alguna otra manera de lograr seguridad de hilo sin recurrir a bloqueos?
¿Hay alguna otra forma de implementar un generador pseudoaleatorio normal utilizando solo miembros inmutables?
Buena llamada para no llamar a setSeed todo el tiempo, supervisión estúpida –
Me gusta esta idea. ¿Podría explicar la opción de expresión de cálculo (no estoy familiarizado con el concepto)? –
Se vería algo así como: 'rnd { let! a = GetNext 10; deja! b = GetExponential 2.5; deja! c = GetNormal; return a, b, c } ' – IngisKahn