Estoy tratando de escribir una función C ++ que devolverá valores aleatorios gaussianos, dadas sus medias y variaciones.
Hay una función de biblioteca rand()
, que devuelve números aleatorios entre 0
y RAND_MAX
. RAND_MAX
no tiene un valor fijo, pero se garantiza que será al menos . Su PDF es uniforme.
Estoy usando el Teorema del límite central para transformar esto rand()
en una variable gaussiana. Lo que estoy haciendo exactamente es llamar rand()
a un usuario las horas especificadas, luego sumar sus valores de retorno, luego cambiar su media a la media especificada por el usuario.
En el trazado anterior, llamé a mi generador aleatorio gaussiano veces y tracé las frecuencias de sus valores de retorno. Como puede ver, su variación es enorme, ya que se crea mediante la suma de muchos otros valores aleatorios.
Devuelve con éxito una variable gaussiana con un PDF gaussiano y con el valor medio especificado. Sin embargo, el problema es su varianza. Estoy atascado en este punto, porque no sé cómo cambiar su variación al valor especificado por el usuario.
Este es mi código (incompleto por ahora; se ignora el parámetro "Varianza"):
template <class T>
T Random::GetGaussian(T Mean /*= 0*/, T Variance /*= 1*/)
{
T MeanOfSum = NUM_GAUSSIAN_SUMS / static_cast<T>(2);
T Rand = 0;
for (uint64_t i=0; i<NUM_GAUSSIAN_SUMS; i++)
{
Rand += static_cast<T>(rand()) / RAND_MAX;
}
return Rand - (MeanOfSum - Mean);
}
Suponga que NUM_GAUSSIAN_SUMS
es 100 y RAND_MAX
es 32767.
Quiero cambiar la varianza de la variable aleatoria de acuerdo con el parámetro de la función. Mi pregunta es, ¿cómo puedo cambiar la varianza de esta variable aleatoria? ¿Cómo puedo hacerlo?
Respuestas:
Su algoritmo inicial crea una variable aleatoria que se distribuye uniformemente entre 0 y 1. La varianza de eso es 1/12. Si sumas
NUM_GAUSSIAN_SUMS
instancias de eso, la varianza seráNUM_GAUSSIAN_SUMS/12
. Para llegar a una varianza objetivoV
, debe multiplicar la variable aleatoria sumada consqrt(V*12/NUM_GAUSSIAN_SUMS)
.Como nota al margen, una plantilla funcionará razonablemente bien para flotadores y dobles, pero habrá problemas numéricos significativos con cualquier tipo de punto fijo.
fuente
Por multiplicación, por supuesto. La varianza de , donde es la constante multiplicativa y es la variable aleatoria, es la varianza de .c X c 2 XcX c X c2 X
fuente
¡Hay otra manera!
Piénsalo, ¿y si quisieras alguna otra distribución en lugar de Gauss? En ese caso, no podrías usar el teorema del límite central; ¿Cómo lo resuelves entonces?
Hay una manera de convertir una variable aleatoria uniforme en PDF arbitrario. Este método se llama Método de transformación inversa
Si se distribuye uniformemente en el intervalo (0, 1), entoncesU[0−1]
tiene cdf .FX(x)
Por lo tanto, todo lo que necesita hacer es aplicar la función CDF inversa a la variable que ha recuperado de la muestra de rv uniforme.
Además, a diferencia de los métodos anteriores, esto no requerirá ninguna iteración y no dependerá de cuántas iteraciones se tomarán para hacer que los resultados se acerquen a Gauss.
Aquí está una de las referencias que da prueba de esto.
fuente