Генерація (псевдо) випадкових чисел, c для людей

У навчальних алгоритмічних військово-політичні завдання досить часто зустрічається необхідність генерації випадкових цілих чисел. Звичайно, можна отримувати їх від користувача, але з заповненням масиву випадковими числами в кількості 100 штук можуть виникнути проблеми.

На допомогу нам приходить функція стандартної бібліотеки мови Сі (НЕ C ++) rand ().

Вона генерує псевдовипадкове ціле число на інтервалі значень від 0 до RAND_MAX. Останнє є константою, яка варіюється в залежності від реалізації мови, але в більшості випадків становить 32767.
А що якщо нам потрібні випадкові числа від 0 до 9? Типовий вихід із ситуації - використання операції ділення по модулю.

Якщо нам потрібні числа від 1 (а не від 0) до 9, то можна додати одиницю ...

Ідея така: генеруємо випадкове число від 0 до 8, і після додавання 1 воно перетворюється в випадкове число від 1 до 9.

І останнє, найсумніше.
На жаль, функція rand () генерує псевдовипадкові числа, тобто числа, які здаються випадковими, але насправді є послідовністю значень, обчислених по хитрому алгоритму, як параметр приймає так зване зерно (seed). Тобто згенеровані функцією rand () числа будуть залежати від значення, яке має зерно в момент її виклику. А зерно завжди встановлюється компілятором в значення 1. Іншими словами, послідовність чисел буде хоч і псевдослучайной, але завжди однаковою.
А це не те, що нам треба.

Виправити ситуацію допомагає функція srand ().

void srand (unsigned int seed);

Вона встановлює зерно рівним значенню параметра, з яким була викликана. І послідовність чисел теж буде інша.

Але проблема залишилася. Як зробити випадковим зерно, адже від нього все залежить?
Типовий виходить із ситуації - використання функції time ().

time_t time (time_t * timer);

Тепер значення цієї функції ми можемо передати в функцію srand () (при цьому виконується неявне приведення типу), і у нас буде чудове випадкове зерно.
І числа будуть чудові і неповторним.

Для використання функцій rand () і srand () потрібно підключити заголовний файл . а для використання time () - файл .

Ось повноцінний приклад.

#include
#include
#include

using namespace std;

int main ()
<
cout <<"10 random numbers (1..100): " < srand (time (NULL));
for (int i = 0; i<10;i++) cout < cin.get ();
return 0;
>

Ось код для сі ++ (mingw compiler):
#include
...
int RandomHi (int hi)
srand (GetTickCount ());
return rand () hi;
>;

Правильніше буде використовувати GetTickCount (), адже у випадку з time (NULL) значення в перебігу однієї секунди будуть однакові, що в деяких слуае неприйнятно.

А до речі, ви знаєте, що при такому підході щільність розподілу випадкової величини НЕ буде рівномірною, а буде зміщена в бік менших чисел? Наприклад, для «rand ()% 100» ймовірність отримати число від 0 до 67 включно буде трохи вище, ніж від 68 до 99. на 1000 сходинка в щільності між 767 і 768 буде ще помітніше.
Рівномірна щільність вийде тільки для подільників, кратних ступеням двійки.
PS: А «» взагалі не можна використовувати. Абсолютно незрозуміло, що товариш Radiocity мав під цим на увазі.

Тут виникло питання: а хіба побітовим «І» ми доб'ємося потрібного випадкового числа? Адже деякі значення з цільового діапазону взагалі виявляться недосяжні.

Схожі статті