Я хотел бы произвести некоторые псевдослучайные числа, и вплоть до сих пор я был очень доволен библиотекой .NET Random.Next(int min, int max)
функция. PRNGs этого разнообразия, как предполагается, используют Однородное распределение, но я очень хотел бы произвести некоторые числа, используя Показательное Распределение.
Я программирую в C#, хотя я приму псевдокодекс или C ++, Ява и т.п.
Какие-либо предложения / фрагменты кода / алгоритмы / мысли?
Поскольку у вас есть доступ к равномерному генератору случайного номера, генерируя случайное число, распределенное с другим распределением, CDF, которого вы знаете, легко с использованием метода инверсии .
Итак, генерируют равномерное случайное число U
, в [0,1)
, затем рассчитать x
:
x = log ( 1-u) / (
-λ )
,
, где λ - параметр скорости экспоненциального распределения. Теперь x
- случайное число с экспоненциальным распределением. Обратите внимание, что вход выше
выше ln
, натуральный логарифм.
Если я понимаю вашу проблему, и вы можете принять конечное число PRNG, вы можете следовать подходу, как:
Это было то, что я использовал, когда столкнулся с аналогичными требованиями:
// sorry.. pseudocode, mine was in Tcl:
int weighted_random (int max) {
float random_number = rand();
return floor(max - ceil( max * random_number * random_number))
}
, конечно, это формула квадрата случайного числа, поэтому вы генерируете случайное число вдоль квадратичной кривой Отказ
Фундаментальная теорема отбора проб удерживает, что если вы можете нормализовать, интегрировать и инвертировать желаемое распределение, которое вы можете бесплатно.
Если у вас есть желаемое распределение f (x)
, нормировали на [A, B]
. Вы рассчитываете
C(y) = \int_a^y F(x) dx
, чтобы получить C ^ {- 1}
, рисуйте Z
равномерно на [0,1) и найдите
x_i = C^{-1}(z_i)
, которые будут иметь желаемое распределение.
В вашем случае: f (x) = ke ^ {- kx}
, и я предполагаю, что вы хотите [0, бесконечность]
. Мы получаем:
C(y) = 1 - e^{-ky}
, которые обратно предоставляют
x = -1/k ln(1 - z)
для Z, брошенные равномерно на [0,1)
.
Но, честно говоря, использование хорошо отлаженной библиотеки является умнее, если вы не делаете это для собственной редакции.
Если вы хотите хорошие случайные числа, рассмотрите связь с процедурами GSL: http://www.gnu.org/software/gsl/ . У них есть рутина gsl_ran_exponential
. Если вы хотите создать случайные номера, используя встроенный генератор с равномерным распространением на [0, 1) (например, U = Random.Next (0, N-1) / N, для некоторого большого n), то просто используйте:
-mu * log (1-u)
См. RANDIST / EXPONINGE.C в источнике GSL.
Редактировать: только для сравнения с некоторыми последующими ответами - это эквивалентно MU = 1 / Lambda. Му вот среднее значение распределения, также называемое параметром масштаба на странице Wikipedia, OP, связанный с oct, и лямбда - это параметр ставки.
Одно интересное свойство экспоненциального распределения: рассмотрите процесс прибытия с экспоненциальным временем взаимодействия. Занять любой период времени (T1, T2) и прибытия в этот период. Эти прибытия равномерно распределены между T1 и T2. (Шелдон Росс, стохастические процессы).
Если у меня есть генератор псевдослучайных чисел и по какой-то причине (например, мое программное обеспечение не может рассчитать журналы), вы не хотите делать вышеуказанные преобразования, но хотят экспоненциальный R.V. С средним из 1.0.
Вы можете:
1) Создать 1001 U (0,1) случайные переменные.
2) Сортировать по порядку
3) Вычтите второй от первого, третьего от второго, ... чтобы получить 1000 различий.
4) Эти различия являются экспоненциальными RVS с распределением со средним значением = 1,0.
Менее эффективное, я думаю, но средство для того же конца.