2009-11-13 94 views
8

Necesito generar números aleatorios a partir de la distribución Binomial (n, p).C#: Algoritmo numérico para generar números a partir de la distribución Binomial

Una variable aleatoria binomial (n, p) es la suma de n variables uniformes que toman 1 con probabilidad p. En el pseudo código, x=0; for(i=0; i<n; ++i) x+=(rand()<p?1:0); generará una Binomial (n, p).

Necesito generar esto tanto para n grande como para pequeño, por ejemplo n = 10^6 yp = 0.02. ¿Hay algún algoritmo numérico rápido para generarlo?

EDITAR -

En este momento esto es lo que tengo como aproximación (junto con las funciones para la distribución exacta de Poisson y Normal) -

public long Binomial(long n, double p) { 
     // As of now it is an approximation 
     if (n < 1000) { 
      long result = 0; 
      for (int i=0; i<n; ++i) 
       if (random.NextDouble() < p) result++; 
      return result; 
     } 
     if (n * p < 10) return Poisson(n * p); 
     else if (n * (1 - p) < 10) return n - Poisson(n * p); 
     else { 
      long v = (long)(0.5 + nextNormal(n * p, Math.Sqrt(n * p * (1 - p)))); 
      if (v < 0) v = 0; 
      else if (v > n) v = n; 
      return v; 
     } 
    } 

+0

¿Funciona bien la distribución de Poisson para 'n * p <10' o para' n * (1 - p) <10'? ¿Cómo es que eliges esa distribución? – HelloGoodbye

+0

Sí, para n grande. Binomial (n, lambda/n) converge a Poisson (lambda), ya que n va al infinito. – KalEl

Respuesta

4

Si está dispuesto a pagar, eche un vistazo a NMath por Centerspace.

De lo contrario, el código C utilizado por el programa Stats R es here, y debe ser fácil de portar a C#.

EDITAR: Hay detalles (incluido el código) sobre la creación de un método para esto en p178 de Practical Numerical Methods with C# por Jack Xu.

OTRA EDICIÓN: A free C# library que hace lo que quiere.

3

No hay manera obvia para hacer esto de manera eficiente Para n pequeña, también puede usar la fórmula para calcular el PDF inverso. Para una n mayor, probablemente sea mejor que uses uno de los approximations to other distributions que son más fáciles de calcular.

+0

En realidad estoy usando alguna rutina de aproximación adhoc que escribí que usa las distribuciones Poisson y Normal. Sin embargo, no estoy seguro de qué tan lejos de los números que genera será estadísticamente desde un verdadero binomio. He agregado mi código como una edición. – KalEl

4

Otra opción sería muestrear desde Normal o Poisson como lo hace y luego agregar un paso Metropolis-Hastings para aceptar o rechazar su muestra. Si acepta que ha terminado, si lo rechaza, debe volver a muestrearlo por completo nuevamente. Mi suposición es que debido a que la aproximación es tan cercana, casi siempre obtendrás un paso de aceptación, de vez en cuando podrías rechazarlo.

También Luc Devroye's book tiene algunos algoritmos geniales para el muestreo binomial.

PD Si termina con un buen algoritmo; ¿Te importaría compartirlo en Math.Net Numerics?

Cuestiones relacionadas