#cpp #c #алгоритм #математика #теория_вероятностей
Хочу воспользоваться первым вариантом этого метода, чтобы генерировать псевдослучайные
числа с нормальным распределением.
Метод может сгенерировать два псевдослучайных числа, но мне нужно только одно. Могу
ли я использовать только одну из этих формул (только с синусом или только с косинусом)?
Будет ли распределение столь же нормальным, как если использовать их обе?
Код на C++:
const float pi = 3.1415926535;
float RandomFloat()
{
return (float) rand() / RAND_MAX;
}
float normalRand()
{
float z = RandomFloat();
float f = RandomFloat();
float r = cos(2 * pi * f) * sqrt(-2 * log(z));
return r;
}
Я понимаю, что это недоиспользование возможностей алгоритма, что программу можно
было бы оптимизировать, но мне не нужна такая большая производительность.
Ответы
Ответ 1
1) Из прикреплённой Вами же ссылки можно сделать вывод, что можно использовать и одно число: Тогда z 0 и z 1 будут независимы и распределены нормально с математическим ожиданием 0 и дисперсией 1. При реализации на компьютере обычно быстрее не вычислять обе тригонометрические функции — cos и sin — а рассчитать одну из них через другую. Основное тригонометрическое тождество: sin^2(x) + cos^2(x) = 1; Выведите из него одно или пару случайных чисел. 2) Используйте srand от времени на Вашем компьютере, так возвращаемые значения rand() будут всегда разные. Пример: srand( time( 0 ) ); // автоматическая рандомизация cout << "rand_value = " << 1 + rand() % 10 << endl; // rand()%10 - возвращает значения от 0 до 9. UPD1: Подозреваю, что Преобразование Бокса — Мюллера здесь не зря используется и Вам нужно 2 величины. На всякий случай оставлю ссылку на небольшую статейку: тык. UPD2: Пояснение почему можно использовать любую из двух формул для просто случайного числа с "нормальным" распределением: Формулы отличаются лишь косинусом и синусом. И косинус, и синус принимают значения от -1 до 1. Это полученное значение мы умножаем на одно и то же выражение.Ответ 2
Экспериментируем... 10000 пар чисел и 20000 первых чисел загоняем в Wolfram Mathematica и просим построить две гистограммы. Похоже на то, что вполне можно использовать только одно число. Можно и детальнее, разницы нет. Рекомендуемый вариант - int main() { random_device rd{}; mt19937 gen{rd()}; normal_distribution<> d{0,1}; for(int i = 0; i < 20000; ++i) cout << d(gen) << " "; } Гистограмма, впрочем, такая же :)Ответ 3
Могу ли я использовать только одну из этих формул (только с синусом или только с косинусом)? Будет ли распределение столь же нормальным, как если использовать их обе? Да, но практичней будет вычислять оба и второе значение использовать при последующих запросах к функции. Но следует иметь ввиду, что это не очень хороший генератор (как и все наивные варианты использования rand()) — для типового размера RAND_MAX в 32768 этот алгоритм не будет выдавать результаты ≥4.57... да и у меньших значений статистика наверняка испортится.
Комментариев нет:
Отправить комментарий