2009-11-13 5 views
8

Мне нужно генерировать случайные числа из биномиального (n, p) распределения.C#: числовой алгоритм для генерации чисел из биномиального распределения

Биномиальная (n, p) случайная величина представляет собой сумму n равномерных переменных, которые принимают 1 с вероятностью p. В псевдокоде x=0; for(i=0; i<n; ++i) x+=(rand()<p?1:0); будет генерировать биномиальный (n, p).

Мне нужно сгенерировать это для малого и очень большого n, например n = 10^6 и p = 0,02. Есть ли какой-нибудь быстрый численный алгоритм для его создания?

EDIT -

Прямо сейчас это то, что я имею в приближении (наряду с функциями для точного Пуассона и нормальное распределение) -

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

Хорошо ли работает распределение Пуассона для 'n * p <10' или для' n * (1 - p) <10'? Как вы выбираете этот дистрибутив? – HelloGoodbye

+0

Да, для больших n. Биномиальное (n, lambda/n) сходится к Пуассону (лямбда), поскольку n переходит в бесконечность. – KalEl

ответ

4

Если вы готовы заплатить, ознакомьтесь с NMath от Centerspace.

В противном случае код C, используемый программой статистики R, равен here и должен быть простым для порта C#.

EDIT: есть информация (например, код) о создании метода для этого на p178 из Practical Numerical Methods with C# от Jack Xu.

ДРУГОЕ ИЗОБРАЖЕНИЕ: A free C# library это делает то, что вы хотите.

3

Там нет очевидного способа чтобы сделать это эффективно. Для небольшого n вы также можете использовать формулу для вычисления обратного PDF. Для большего n вы, вероятно, лучше всего используете один из approximations to other distributions, который проще рассчитать.

+0

Я на самом деле использую некоторую процедуру аппроксимации adhoc, которую я написал, которая использует распределения Пуассона и Нормала. Однако я не уверен, насколько далеко от чисел, которые он генерирует, будет статистически быть от истинного Binomial. Я добавил свой код в качестве редактирования. – KalEl

4

Другим вариантом будет выборка из Normal или Poisson, как вы это делаете, а затем добавьте шаг Metropolis-Hastings, чтобы принять или отклонить образец. Если вы согласны с тем, что все сделано, если вы отклоните, вам придется полностью повторить выбор. Я предполагаю, что, поскольку приближение настолько близко, вы почти всегда получите шаг принятия, время от времени вы можете отклонить.

Также у Luc Devroye's book есть несколько отличных алгоритмов для биномиальной выборки.

PS Если у вас есть хороший алгоритм; не могли бы вы поделиться им по адресу Math.Net Numerics?

Смежные вопросы