0Pricing
C++ Academy · Lekcja

Prawidłowe inicjowanie ziarna

Uzyskuj powtarzalne wyniki losowania

Prawidłowe inicjowanie ziarna to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C++ Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C++ Academy zawiera 4 lekcji w sumie.

Czym jest ziarno?

Ziarno to stan początkowy silnika. To samo ziarno odtwarza tę samą sekwencję, a inne ziarno daje inną sekwencję.

#include <iostream>
#include <random>

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

Stałe ziarno zapewniające powtarzalność

Stałe ziarno sprawia, że wyniki są powtarzalne, co jest idealne podczas testowania i debugowania.

#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 dostarcza niedeterministyczne ziarna z systemu operacyjnego. Należy użyć go raz do zainicjalizowania silnika.

#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;
}

Jednorazowa inicjalizacja i ponowne użycie

Silnik należy zainicjalizować tylko raz podczas uruchamiania programu. Ponowna inicjalizacja przed każdym losowaniem pogarsza jakość losowości.

#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;
}

Pułapka związana z ziarnem opartym na czasie

Inicjalizacja za pomocą time(nullptr) zmienia się tylko raz na sekundę, dlatego programy uruchomione w tym samym czasie otrzymują tę samą sekwencję. Lepiej użyć 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;
}

Inicjalizacja za pomocą seed_seq

Silnik ma dużo stanu wewnętrznego. std::seed_seq rozprowadza kilka wartości ziarna po całym tym stanie, zapewniając lepszą inicjalizację.

#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;
}

Łączenie wartości random_device

Aby uzyskać wysoką jakość inicjalizacji, należy zebrać kilka wartości z random_device w obiekcie 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;
}

Jawna ponowna inicjalizacja

Istniejący silnik można zresetować za pomocą seed(value), aby rozpocząć jego sekwencję ponownie od znanego punktu.

#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;
}

Zapisywanie i przywracanie stanu

Stan silnika można zapisać do strumienia, a następnie z niego odczytać, co pozwala zapisać i wznowić dokładnie ten sam stan losowania.

#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 nie zapewnia powtarzalności

Ponieważ random_device jest niedeterministyczny, nie należy go używać, gdy konieczne jest odtworzenie przebiegu programu. W tym celu należy użyć stałego ziarna.

#include <iostream>
#include <random>

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

Generator wielokrotnego użytku

Popularny wzorzec polega na ukryciu zainicjalizowanego silnika za niewielkim pomocnikiem, dzięki czemu reszta kodu po prostu pobiera liczby.

#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;
}

Szybkie sprawdzenie

Proszę sprawdzić swoją wiedzę na temat inicjalizacji ziarnem.

Podsumowanie

Dowiedzieli się Państwo, jak prawidłowo inicjalizować ziarna:

  • stałe ziarno zapewnia powtarzalne przebiegi, a std::random_device — unikatowe
  • ziarno należy ustawiać raz podczas uruchamiania programu, a nie przed każdym losowaniem; należy unikać mało dokładnego ziarna opartego na time()
  • seed_seq rozprowadza entropię po całym silniku, a stan silnika można zapisywać i przywracać za pomocą strumieni

W następnym kroku zastosują Państwo to wszystko w praktycznych przykładach.

Często zadawane pytania

Czy lekcja „Prawidłowe inicjowanie ziarna” jest bezpłatna?

Tak — pełny tekst „Prawidłowe inicjowanie ziarna” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C++ Academy, przejdź na CoddyKit PRO. Kurs C++ Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Prawidłowe inicjowanie ziarna”?

Uzyskuj powtarzalne wyniki losowania Ćwiczysz C++ Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C++ Academy?

Nie wymagamy żadnego doświadczenia. C++ Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Prawidłowe inicjowanie ziarna”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C++ Academy?

Tak. Każda lekcja C++ Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Silniki losowe
  2. Rozkłady
  3. Prawidłowe inicjowanie ziarna
  4. Praktyczne przykłady
← Powrót do C++ Academy