Глиф Учебники

Случайные числа в C++

Справочник · C++ · 2 минуты чтения

C++
#include <iostream>
#include <random>
using namespace std;

int main() {
    random_device rd;
    mt19937 gen(rd());
    uniform_int_distribution<int> dice(1, 6);
    for (int i = 0; i < 10; i++) {
        cout << dice(gen) << " ";
    }
    cout << "\n";
    return 0;
}

Программа выводит 10 случайных чисел от 1 до 6 включительно, и при каждом запуске — разные.

Из чего это собрано (всё из <random>):

Дробные числа и перемешивание

C++
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    mt19937 gen(random_device{}());
    uniform_real_distribution<double> unit(0.0, 1.0);
    cout << unit(gen) << "\n";          // от 0 до 1, единица не входит

    vector<int> cards = {1, 2, 3, 4, 5};
    shuffle(cards.begin(), cards.end(), gen);
    for (int c : cards) {
        cout << c << " ";
    }
    cout << "\n";
    return 0;
}

uniform_real_distribution<double>(a, b) даёт дробные числа от a до b, причём b не входит. shuffle перемешивает вектор в случайном порядке.

Одинаковые числа при каждом запуске

Иногда это и нужно: при отладке удобно, чтобы «случайные» данные повторялись. Задайте зерно числом: mt19937 gen(12345); — последовательность будет одной и той же при каждом запуске. Но разные компиляторы могут по-разному переводить её в числа диапазона, поэтому в g++ и в Visual Studio результаты uniform_int_distribution с одним зерном могут отличаться.

В старых версиях MinGW для Windows random_device выдавал одно и то же при каждом запуске. Если числа не меняются, возьмите зерно от часов: mt19937 gen(chrono::steady_clock::now().time_since_epoch().count()); (нужен #include <chrono>).

А rand()?

В старом коде и учебниках встречается rand() из <cstdlib>:

C++
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(0));
    int x = rand() % 100 + 1;       // от 1 до 100
    cout << x << "\n";
    return 0;
}

Для простой игры этого хватит, но у rand есть недостатки:

Частые ошибки