Функция rand в C++: генерация случайных чисел

Привет! В этой статье речь пойдет о популярной функции в C++ для генерации случайных чисел - rand. Начнем мы с обзора этой функции и разберемся, как ее правильно использовать. Посмотрим как эта функция себя ведет на нескольких примерах, а закончим написанием своего простенького генератора случайных чисел.

Иллюстрация rand

Как сгенерировать случайное число в C++

Для генерации случайных чисел в C/C++ можно использовать функцию rand:

int rand (void);
  • Эта функция не принимает никаких аргументов.
  • Возвращает эта функция случайное число от нуля до RAND_MAX (зависит от компилятора. У меня RAND_MAX = 2147483647).

Давайте посмотрим на простую программу, которая выводит случайные числа сгенерированные с помощью функции rand:

#include <iostream>
using namespace std;

int main() {
  cout << "rand() = " << rand() << endl;
  cout << "rand() = " << rand() << endl;
  cout << "rand() = " << rand() << endl;

  return 0;
}

И теперь давайте запусти ее:

rand() = 16807
rand() = 282475249
rand() = 1622650073

И еще раз:

rand() = 16807
rand() = 282475249
rand() = 1622650073

Хм… Какие-то случайные числа не очень-то и случайные. Дело в том, что мы работаем с псевдослучайными числами. Эти числа вычисляются по математической формуле и только выглядят случайными. На самом деле каждое следующее число зависит от предыдущего. Как вы уже можете догадаться, при старте программы это стартовое число одно и тоже.

Давайте поменяем этот seed (стартовое число) при старте программы, чтобы случайные числа были разные при каждом запуске:

#include <ctime>
#include <iostream>
using namespace std;

int main() {
  srand(time(0));

  cout << "rand() = " << rand() << endl;
  cout << "rand() = " << rand() << endl;
  cout << "rand() = " << rand() << endl;

  return 0;
}

Первый запуск:

rand() = 871916998
rand() = 2028061905
rand() = 775992151

Второй запуск:

rand() = 871849770
rand() = 898160909
rand() = 727842800

Так-то лучше. Конечно, использовать time(0) вовсе не обязательно. Вы можете выбрать seed как вам угодно.

Генерация случайных чисел в диапазоне

Просто случайное число нам нужно довольно редко. Обычно мы хотим получить число, которое будет находиться в каком-то диапазоне (например от десяти до двадцати включительно). Для этого есть стандартный прием с остатком от деления и сложением:

int start = 10;
int end = 20;
int x = rand() % (end - start + 1) + start;

Как вы можете видеть, мы сначала “обрезаем” сгенерированное число до нужного нам размера с помощью остатка от деления, а потом сдвигаем его так, чтобы 0 стал равен началу диапазона.

В C++ есть библиотека, специально предназначенная для всего случайного - <random>. Она позволяет генерировать случайные числа в диапазоне не используя трюков с остатком от деления.

Что будет выведено на экран:

int start = 10;
int end = 30;
int x = rand() % (end - start + 1) + start;
cout << x << endl;
Случайное число от 1 до 30.
Случайное число от 10 до 30.
Случайное число от 0 до 30.
Случайное число от 10 до 29.

Простая реализация генератора случайных чисел

Теперь давайте попробуем реализовать генератор случайных чисел не используя библиотечных функций вроде rand:

#include <ctime>
#include <iostream>
using namespace std;

unsigned long seed = 1;  // это то самое стартовое значение,
                         // о котором мы говорили ранее

int my_rand() {
  seed = seed * 1103515245 + 12345;  // Линейный конгруэнтный метод
  return (seed / 65536) % 32768;     // Вернуть значение в диапазоне 0-32767
}

int main() {
  cout << "my_rand() = " << my_rand() << endl;
  cout << "my_rand() = " << my_rand() << endl;
  cout << "my_rand() = " << my_rand() << endl;

  return 0;
}

Вывод программы:

my_rand() = 16838
my_rand() = 5758
my_rand() = 10113

Поздравляю! Вы реализовали свой собственный простейший генератор случайных чисел!

Упражнения

  1. Использование функции rand:
    Напишите программу на C++, которая генерирует три случайных числа с помощью функции rand и выводит их на экран. Затем измените программу так, чтобы она использовала time(0) в качестве seed’a и снова выведите три случайных числа.

  2. Генерация случайных чисел в диапазоне:
    Используя пример в статье, напишите программу, которая генерирует три случайных числа в диапазоне от 50 до 100 и выводит их на экран. Затем измените программу так, чтобы диапазон был от -100 до 100.

  3. Создание своего генератора случайных чисел:
    Используя пример в статье, создайте свою версию функции rand. Ваша программа должна генерировать три случайных числа с помощью вашей функции и выводить их на экран.

Обсуждение