Хочу воспользоваться первым вариантом этого метода, чтобы генерировать псевдослучайные числа с нормальным распределением.
Метод может сгенерировать два псевдослучайных числа, но мне нужно только одно. Могу ли я использовать только одну из этих формул (только с синусом или только с косинусом)? Будет ли распределение столь же нормальным, как если использовать их обе?
Код на 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) Из прикреплённой Вами же ссылки можно сделать вывод, что можно использовать и одно число:
Тогда 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. Это полученное значение мы умножаем на одно и то же выражение.
Экспериментируем...
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) << " ";
}
Гистограмма, впрочем, такая же :)
Могу ли я использовать только одну из этих формул (только с синусом или только с косинусом)? Будет ли распределение столь же нормальным, как если использовать их обе?
Да, но практичней будет вычислять оба и второе значение использовать при последующих запросах к функции.
Но следует иметь ввиду, что это не очень хороший генератор (как и все наивные варианты использования rand()
) — для типового размера RAND_MAX
в 32768
этот алгоритм не будет выдавать результаты ≥4.57... да и у меньших значений статистика наверняка испортится.
Виртуальный выделенный сервер (VDS) становится отличным выбором
как можно запретить ввод букв внутри терминала? Жмем клавишу, программа сразу отрабатывает, понимает, что это буква и ничего не происходитЖмем...
Изучаю Spring на IDE IntelJIdeaХочу почитать что делает тот или иной метод, аннотация