De this question: Random number generator which gravitates numbers to any given number in range? Investigué un poco ya que me encontré con un generador de números aleatorios. Todo lo que recuerdo es el nombre "Mueller", así que supongo que lo encontré, aquí:Implementando el generador de números aleatorios Box-Mueller en C#
puedo encontrar numerosas implementaciones de la misma en otros idiomas, pero me parece que no puede implementarlo correctamente en C#.
Esta página, por ejemplo, The Box-Muller Method for Generating Gaussian Random Numbers dice que el código debería tener este aspecto (esto no es C#):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
double
gaussian(void)
{
static double v, fac;
static int phase = 0;
double S, Z, U1, U2, u;
if (phase)
Z = v * fac;
else
{
do
{
U1 = (double)rand()/RAND_MAX;
U2 = (double)rand()/RAND_MAX;
u = 2. * U1 - 1.;
v = 2. * U2 - 1.;
S = u * u + v * v;
} while(S >= 1);
fac = sqrt (-2. * log(S)/S);
Z = u * fac;
}
phase = 1 - phase;
return Z;
}
Ahora, aquí está mi aplicación de lo anterior en C#. Tenga en cuenta que la transformación produce 2 números, de ahí el truco con la "fase" anterior. Simplemente descarto el segundo valor y devuelvo el primero.
public static double NextGaussianDouble(this Random r)
{
double u, v, S;
do
{
u = 2.0 * r.NextDouble() - 1.0;
v = 2.0 * r.NextDouble() - 1.0;
S = u * u + v * v;
}
while (S >= 1.0);
double fac = Math.Sqrt(-2.0 * Math.Log(S)/S);
return u * fac;
}
Mi pregunta es la siguiente escenario específico, donde mi código no devuelve un valor en el rango de 0-1, y no puedo entender cómo el código original sea posible.
- u = 0,5, v = 0,1
- S se convierte en
0.5*0.5 + 0.1*0.1
=0.26
- FAC se convierte en ~
3.22
- el valor de retorno es, pues, ~
0.5 * 3.22
o ~1.6
Eso no está dentro de 0 .. 1
.
¿Qué estoy haciendo mal/no estoy entendiendo?
Si modifico mi código para que en vez de multiplicar fac
con u
, multiplico por S
, puedo obtener un valor que oscila entre 0 y 1, pero tiene la mala distribución (parece tener una distribución máxima alrededor de 0,7- 0.8 y luego se estrecha en ambas direcciones.)
Tenga en cuenta que he comprobado un par de ejemplos del código anterior, por lo general en C o Java, y todos se ven más o menos iguales. –
¿Estás seguro de que el código C genera exactamente lo que quieres? – Euphoric