2010-05-01 29 views
30

Quiero generar números aleatorios con un rango (n a m, p. Ej. 100 a 150), pero en lugar de ser puramente aleatorios quiero que los resultados se basen en la distribución normal.Número aleatorio dentro de un rango basado en una distribución normal

Con esto quiero decir que, en general, quiero los números "agrupados" en torno a 125.

que he encontrado este paquete de números aleatorios que parece tener mucho de lo que necesito: http://codeproject.com/KB/recipes/Random.aspx

Se admite una variedad de generadores aleatorios (incluye mersiene twister) y puede aplicar el generador a una distribución.

Pero estoy confundido, si uso un generador de distribución normal, los números aleatorios son de aproximadamente -6 a +8 (aparentemente el verdadero rango es float.min a float.max).

¿Cómo hago una escala que se ajuste a mi rango requerido?

Respuesta

24

Una distribución normal estándar tiene significa 0 y una desviación estándar de 1; si desea hacer una distribución con la media m y la desviación s, simplemente multiplique por s y luego agregue m. Dado que la distribución normal es teóricamente infinita, no puede tener un límite máximo en su rango, p. (100 a 150) sin rechazar explícitamente los números que caen fuera de él, pero con una opción de desviación apropiada puede estar seguro de que (por ejemplo) el 99% de sus números estarán dentro del rango.

Alrededor del 99,7% de una población está dentro de las +/- 3 desviaciones estándar, por lo que si elige la suya será de aproximadamente (25/3), debería funcionar bien.

Así que quieres algo como: (normal * 8.333) + 125

+0

Gracias ... esto tiene mucho sentido :) – ConfusedAgain

+0

De nada. :) – tzaman

2

Esto puede ser demasiado simplista para sus necesidades, pero un & forma barata rápida de obtener un número aleatorio con una distribución que se inclina hacia el centro es simplemente agregar 2 (o más) números aleatorios.

Piense en cuándo tira dos dados de 6 caras y añádalos. La suma es más a menudo 7, luego 6 y 8, luego 5 y 9, etc. y solo raramente 2 o 12.

+0

Teorema del límite central significa que agregar uniformes se aproximará a una distribución normal, pero es hackish y es difícil hacer un seguimiento de la varianza. – tzaman

+1

También requiere tomar una cantidad arbitrariamente grande de muestras para una aproximación dada a una distribución normal. –

4

La respuesta de tzaman es correcta, pero cuando se utiliza la biblioteca vinculada hay una manera más simple que realizar el Cálculo usted mismo: el objeto NormalDistribution tiene propiedades modificables Mu (significando la media) y Sigma (desviación estándar). Entonces, yendo por los números de tzaman, configure Mu en 125 y Sigma en 8.333.

+0

Por supuesto, configurarlos directamente sería más conveniente. :) +1 – tzaman

14

Por el bien de interés, es bastante sencillo para generar números aleatorios distribuidos normalmente a partir de un generador de números aleatorios uniforme (aunque debe hacerse en parejas):

Random rng = new Random(); 
double r = Math.Sqrt(-2 * Math.Log(rng.NextDouble())); 
double θ = 2 * Math.Pi * rng.NextDouble(); 
double x = r * Math.Cos(θ); 
double y = r * Math.Sin(θ); 

x y y contienen ahora dos independientes, normalmente distribuidos números aleatorios con media 0 y varianza 1. Puede escalar y traducirlos según sea necesario para obtener el rango que desea (como lo explica interjay).


Explicación:

Este método se llama el Box–Muller transform.Utiliza la propiedad de la unidad bidimensional gaussiana de que el valor de densidad en sí, p = exp(-r^2/2), se distribuye uniformemente entre 0 y 1 (la constante de normalización se eliminó por simplicidad).

Dado que puede generar tal valor fácilmente utilizando un uniforme RNG, termina con un contorno circular de radio r = sqrt(-2 * log(p)). A continuación, puede generar una segunda variante aleatoria uniforme entre 0 y 2*pi para darle un ángulo θ que define un punto único en su contorno circular. Finalmente, puede generar dos variables aleatorias normales i.i.d. transformando las coordenadas polares (r, θ) en coordenadas cartesianas (x, y).

Esta propiedad, que p se distribuye uniformemente, no es válida para otras dimensionalidades, por lo que debe generar exactamente dos variables normales a la vez.

+0

Interesante. ¿Este método tiene un nombre? Me gustaría leer más sobre esto. Esta es una aproximación, ¿verdad? –

+1

@Drew: Se llama la transformación Box-Muller: http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform –

+1

Gracias. Anoté aquí (http://stackoverflow.com/questions/2325472/generate-random-numbers-following-a-normal-distribution-in-cc/2325531#2325531) la sugerencia de que puede aferrarse a 'u2' y usar como 'u1' para la siguiente llamada, como una optimización. No hay mención de esto en el artículo de Wikipedia. ¿Puedes comentar si esto mantiene la aleatoriedad? –

-1

Aquí hay otro algoritmo que no necesita calcular Sin/Cos, ni necesita saber Pi. No me preguntes sobre los antecedentes teóricos. Lo encontré en algún lugar una vez y es lo que he estado usando desde entonces. Sospecho que es una especie de normalización de la misma transformación de Box-Muller que @Will Vousden menciona. También produce resultados en pares.

El ejemplo es VBscript; lo suficientemente fácil de convertir a cualquier otro idioma.

Sub calcRandomGauss (byref y1, byref y2) 
    Dim x1, x2, w 
    Do 
     x1 = 2.0 * Rnd() - 1.0 
     x2 = 2.0 * Rnd() - 1.0 
     w = x1 * x1 + x2 * x2 
    Loop While w >= 1.0 Or w = 0 'edited this line, thanks Richard 

    w = Sqr((-2.0 * Log(w))/w) 
    y1 = x1 * w 
    y2 = x2 * w 
End Sub 
+1

"No me preguntes sobre los antecedentes teóricos. Lo he encontrado en alguna parte una vez". Así es como el conocimiento incorrecto se propaga. Esta es una mala implementación del método polar de Marsaglia. Necesitas hacer un bucle mientras 'w> = 1.0 OR w == 0'. De lo contrario, te arriesgas a tomar 'log (0)' y arruinar tu programa. – Richard

+0

Yo diría todo lo contrario. Ser honesto acerca de no tener ninguna referencia tenía la intención de evitar que el conocimiento incorrecto se propagara. Gracias por la referencia y la corrección. – mgr326639

0

Un enfoque diferente a este problema utiliza la distribución beta (que tiene una gama duro, a diferencia de la distribución normal) y consiste en elegir los parámetros adecuados de tal manera que la distribución tiene la media dada y la desviación estándar (raíz cuadrada de la varianza). Ver this question.

Cuestiones relacionadas