Объясните этот С++ random

Как показано в этом post, существует несколько способов генерировать случайные числа с плавающей запятой в C++. Но я не совсем понимаю 3-й вариант ответа:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

Кто-нибудь может объяснить мне эту строку? Как здесь рассчитываются лимиты?


person David Fenko    schedule 01.03.2014    source источник


Ответы (3)


rand() генерирует случайные числа от 0 до RAND_MAX.

0 <= rand()/RAND_MAX <= 1    
implies: 0 <= rand()/RAND_MAX*(HI-LO) <= HI-LO    
implies: LO <= LO + rand()/RAND_MAX*(HI-LO) <= HI

Теперь, поскольку RAND_MAX и HI-LO являются целыми числами, RAND_MAX/(HI-LO) приводится к типу float.

person Rikayan Bandyopadhyay    schedule 01.03.2014

Г-н STL объяснил, почему это (и другие связанные с rand() конструкции) очень плохая идея в своей презентации "rand() считается вредным".

Идея этого кода состоит в том, чтобы использовать плавающую точку, чтобы уменьшить потерю энтропии случайного числа, ограниченного операцией по модулю.
Как указывает Стивен, решение с плавающей запятой не имеет проблемы, которую вводит операция по модулю (в основном существует интервал значений, которые с большей вероятностью будут сгенерированы, чем другие, благодаря модулю, нарушающему теоретическое единообразие rand()).
Но числа с плавающей запятой вводят новая проблема: округление, производимое при окончательном преобразовании из типа float в целочисленный тип, ожидаемый пользователем, приводит к проблеме, что одно и то же число генерируется много раз для разных входных данных, но несколько значений генерируются только одним< /сильный>. Таким образом, снова теряется единообразие. Конечно, это округление не является проблемой, если целью является создание случайного числа с плавающей запятой, как в вашем случае. Но выполняемые округления и деления также могут привести к нарушению равномерности распределения.

Вывод из всего вышесказанного таков: Этот код пытается решить проблемы единообразия классическим способом по модулю, но приводит (меньше? Я не уверен) к проблемам единообразия. Так что попробуйте заменить случайные возможности C другими библиотеками (например, стандартной <random> библиотекой, представленной начиная с C++11).

person Manu343726    schedule 01.03.2014
comment
почему минус? Я единственный, кто указал, что эта конструкция пытается сделать, и хороший намек на то, почему это неразумный способ, вместо того, чтобы предлагать ОП использовать ее, объясняя, что делает код, а не какова цель кода. - person Manu343726; 01.03.2014
comment
Я проголосовал против, потому что вы не ответили на вопрос. Я удалил отрицательный голос, когда вы отредактировали его, чтобы ответить на вопрос. - person Benjamin Lindley; 01.03.2014
comment
@BenjaminLindley хорошо, извини. Я писал :Р - person Manu343726; 01.03.2014

Он пытается сгенерировать случайное число в диапазоне [LO, HI]

Лучший способ сделать это в C++11 — использовать библиотеку <random>:

std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(LO,HI);
double value = distribution(generator);
person Zac Howland    schedule 01.03.2014