Я пытаюсь написать функцию C ++, которая будет возвращать гауссовские случайные значения, учитывая их средние значения и дисперсии.
Есть библиотечная функция rand()
, которая возвращает случайные числа между 0
и RAND_MAX
. RAND_MAX
не имеет фиксированного значения, но гарантируется, что оно будет не менее . Его PDF является единообразным.
Я использую Центральную предельную теорему, чтобы преобразовать это rand()
в гауссовскую переменную. То, что я точно делаю, это вызов rand()
времени, указанного пользователем, затем сложение его возвращаемых значений, а затем смещение его среднего значения на указанное пользователем среднее.
На графике выше я вызывал мой генератор гауссовских случайных чисел раз и наносил на график частоты его возвращаемых значений. Как видите, его дисперсия огромна, поскольку она создается суммой множества других случайных значений.
Он успешно возвращает гауссову переменную с гауссовым PDF и указанным средним значением. Однако проблема заключается в его дисперсии. Я застрял на этом этапе, потому что я не знаю, как изменить его дисперсию на указанное пользователем значение.
Это мой код (пока неполный; параметр "Дисперсия" игнорируется):
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);
}
Предположим, что NUM_GAUSSIAN_SUMS
это 100 и RAND_MAX
32767.
Я хочу изменить дисперсию случайной величины в соответствии с параметром функции. У меня вопрос, как я могу изменить дисперсию этой случайной величины? Как мне это сделать?
Ответы:
Ваш первоначальный алгоритм создает случайную переменную, которая равномерно распределена между 0 и 1. Разница составляет 1/12. Если вы суммируете
NUM_GAUSSIAN_SUMS
случаи этого отклоненияNUM_GAUSSIAN_SUMS/12
. Чтобы получить целевую дисперсию,V
вам нужно умножить суммированную случайную величину наsqrt(V*12/NUM_GAUSSIAN_SUMS)
.Как примечание, шаблон будет работать достаточно хорошо для чисел с плавающей запятой и двойных чисел, но с любым типом с фиксированной запятой возникнут значительные численные проблемы.
источник
источник
Есть еще один способ!
Подумайте об этом, что, если вы хотите какой-то другой дистрибутив в отличие от гауссовского? В этом случае вы не могли бы использовать теорему о центральном пределе; как ты тогда решаешь это?
Есть способ конвертировать равномерную случайную величину в произвольный PDF. Этот метод называется методом обратного преобразования
Следовательно, все, что вам нужно сделать, это применить обратную функцию CDF к переменной, которую вы извлекли из выборки универсального rv.
Кроме того, в отличие от более ранних методов - это не потребует какой-либо итерации и не будет зависеть от того, сколько итераций будет сделано, чтобы сделать результаты ближе к гауссовскому.
Вот одна из ссылок, которая дает доказательство этого.
источник