0Pricing
C++ Academy · Урок

Правильная инициализация генератора

Получайте воспроизводимую случайность

«Правильная инициализация генератора» — бесплатный урок C++ Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.

Что такое seed

seed — это начальное состояние генератора. Один и тот же seed воспроизводит одну и ту же последовательность, а другой seed даёт другую последовательность.

#include <iostream>
#include <random>

int main() {
    std::mt19937 a(100), b(200);
    std::cout << std::boolalpha << (a() == b()) << '\n';
    return 0;
}

Фиксированный seed для воспроизводимости

Постоянный seed делает результаты воспроизводимыми, что особенно удобно для тестов и отладки.

#include <iostream>
#include <random>

int main() {
    auto run = [](unsigned s) {
        std::mt19937 g(s);
        return g() % 1000;
    };
    std::cout << run(42) << ' ' << run(42) << '\n';
    return 0;
}

std::random_device

std::random_device предоставляет непредсказуемые seed из операционной системы. Используйте его один раз, чтобы задать seed генератору.

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> d(1, 6);
    std::cout << "a roll: " << d(gen) << '\n';
    return 0;
}

Один seed — многократное использование

Задайте генератору seed один раз при запуске программы. Повторная установка seed перед каждым получением значения ухудшает качество случайности.

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());            // seed once
    std::uniform_int_distribution<int> d(1, 100);
    for (int i = 0; i < 3; ++i) std::cout << d(gen) << ' ';
    std::cout << '\n';
    return 0;
}

Проблема seed на основе времени

Инициализация с помощью time(nullptr) меняет seed только раз в секунду, поэтому программы, запущенные одновременно, получают одну и ту же последовательность. Предпочитайте random_device.

#include <iostream>
#include <random>
#include <ctime>

int main() {
    std::mt19937 gen(static_cast<unsigned>(std::time(nullptr)));
    std::cout << "seeded from time (coarse)\n";
    std::cout << (gen() % 100) << '\n';
    return 0;
}

Инициализация с помощью seed_seq

У генератора много внутреннего состояния. std::seed_seq распределяет несколько значений seed по всему состоянию, обеспечивая лучшую инициализацию.

#include <iostream>
#include <random>

int main() {
    std::seed_seq seq{1, 2, 3, 4};
    std::mt19937 gen(seq);
    std::cout << (gen() % 1000) << '\n';
    return 0;
}

Объединение значений random_device

Для качественной инициализации соберите несколько значений из random_device в seed_seq.

#include <iostream>
#include <random>
#include <array>

int main() {
    std::random_device rd;
    std::array<unsigned, 4> seeds{rd(), rd(), rd(), rd()};
    std::seed_seq seq(seeds.begin(), seeds.end());
    std::mt19937 gen(seq);
    std::cout << "well-seeded engine ready\n";
    std::cout << (gen() % 100) << '\n';
    return 0;
}

Явная повторная установка seed

Вы можете сбросить существующий генератор с помощью seed(value), чтобы перезапустить его последовательность с известной точки.

#include <iostream>
#include <random>

int main() {
    std::mt19937 gen(1);
    unsigned first = gen();
    gen.seed(1);             // restart
    std::cout << std::boolalpha << (gen() == first) << '\n';
    return 0;
}

Сохранение и восстановление состояния

Состояние генератора можно вывести в поток, а затем считать обратно, что позволяет сохранить и возобновить точное состояние генератора случайных чисел.

#include <iostream>
#include <sstream>
#include <random>

int main() {
    std::mt19937 gen(5);
    std::ostringstream save; save << gen;
    unsigned expected = gen();
    std::istringstream load(save.str());
    std::mt19937 restored; load >> restored;
    std::cout << std::boolalpha << (restored() == expected) << '\n';
    return 0;
}

random_device не обеспечивает воспроизводимость

Поскольку random_device непредсказуем, никогда не используйте его, если требуется воспроизвести запуск. Для этого используйте фиксированный seed.

#include <iostream>
#include <random>

int main() {
    const unsigned FIXED = 2026;
    std::mt19937 gen(FIXED); // reproducible across runs
    std::cout << (gen() % 10000) << '\n';
    return 0;
}

Повторно используемый генератор

Распространённый подход заключается в том, чтобы скрыть генератор с заданным seed за небольшим вспомогательным компонентом, чтобы остальной код просто запрашивал числа.

#include <iostream>
#include <random>

int roll(std::mt19937& gen) {
    std::uniform_int_distribution<int> d(1, 6);
    return d(gen);
}

int main() {
    std::mt19937 gen(2026);
    std::cout << roll(gen) << ' ' << roll(gen) << '\n';
    return 0;
}

Быстрая проверка

Проверьте понимание инициализации с помощью seed.

Итоги

Вы узнали, как правильно задавать seed:

  • фиксированный seed обеспечивает воспроизводимые запуски, а std::random_device — уникальные последовательности
  • задавайте seed один раз при запуске, а не перед каждым получением значения; избегайте неточного seed на основе time()
  • seed_seq распределяет энтропию по генератору, а состояние генератора можно сохранять и восстанавливать через потоки

Далее Вы примените всё это на практических примерах.

Часто задаваемые вопросы

Урок «Правильная инициализация генератора» бесплатный?

Да — полный текст урока «Правильная инициализация генератора» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.

Чему я научусь в уроке «Правильная инициализация генератора»?

Получайте воспроизводимую случайность Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C++ Academy?

Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Правильная инициализация генератора»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C++ Academy?

Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Генераторы случайных чисел
  2. Распределения
  3. Правильная инициализация генератора
  4. Практические примеры
← Назад к C++ Academy