Wyniki powtarzają się za każdym odpaleniem programu.

0

#include <iostream>
#include <vector>
#include <time.h>
#include <random>
#include <algorithm>


thread_local std::mt19937 gen{ std::random_device{}() };

int main()
{
    srand(time(NULL));
    std::vector<int> pula(49);
    std::iota(pula.begin(), pula.end(), 0);
    std::vector<int> zaklad{ 4,11,17,28,35,47 };
    uint64_t ilosctrafien{ 0 };
    std::cout << std::fixed;
    std::cout.precision(10);
    for (uint64_t j = 0; j < 600000000; j++)
        { 
        std::shuffle(pula.begin(), pula.end(), gen);

        if (std::is_permutation(pula.begin(), pula.begin() + 6, zaklad.begin()))
            {
            ilosctrafien++;
            std::cout << "Wygrana po raz " << ilosctrafien << " Percent: " << (double)j * 100.0 / 600000000.0 << " Success ratio:" << double(ilosctrafien) / (double)j << std::endl;
            }
    }
}

Gdy to skompiluję g++ (MinGW-64) w Windows, to za każdym odpaleniem programu mam te same wyniki. Gdy skompiluję to clangiem lub cl lub g++ w Linuxie - wyniki nie powtarzają się. Nie rozumiem tego.

0

A wiesz, z którego Ty korzystasz generatora? srand/rand czy mt19937? :) W oparciu o co działa std::shuffle?

Wygląda, że MinGw na Windowsie ma schrzanione nowe liczby losowe...

1

Numer permutacji da się policzyć w czasie O(1)
Prawdopodobieństwo trafienia również.

0

Gdy pod Windows skompiluję w g++ poniższy kod i odpalę cztery instancje programu, to zawsze dwie z nich wyświetlają identyczne wyniki, a pozostałe dwie różne informacje. Gdy odpalę sześć instancji, to identyczne wyniki pokazują trzy, parami.

#include <iostream>
#include <vector>
#include <numeric>
#include <time.h>
#include <random>
#include <algorithm>



int main()
{
    srand(time(NULL));
    std::vector<int> pula(49);
    std::iota(pula.begin(), pula.end(), 0);
    std::vector<int> zaklad{ 4,11,17,28,35,47 };
    std::vector<int> wylosowane;
    int los{ 0 };
    int rozmiar{ 0 };
    uint64_t ilosctrafien{ 0 };
    std::cout << std::fixed;
    std::cout.precision(10);
    for (uint64_t j = 0; j < 600000000; j++)
    { 
    for (int i = 0; i < 6; i++)
    {
        rozmiar = pula.size() - 1;
        los = rand() % rozmiar;
        wylosowane.push_back(pula[los]);
        pula.erase(pula.begin() + los);
    }
    if (std::is_permutation(zaklad.begin(), zaklad.end(), wylosowane.begin()))
    {
        ilosctrafien++;
        std::cout << "Wygrana po raz " << ilosctrafien << " Percent: " << (double)j * 100.0 / 600000000.0 << " Success ratio:" << double(ilosctrafien) / (double)j << std::endl;
    }
    pula.clear();
    pula.resize(49);
    std::iota(pula.begin(), pula.end(), 0);
    wylosowane.clear();
    }
}
0

Jak wyjaśniono w komentarzach, random device na starszych wersjach MinGW jest kompletnie deterministyczne.

0

random_shuffle działa na 'rand();'

0

Ale on używa std::shuffle(pula.begin(), pula.end(), gen);, gdzie gen jest std::mt19937 inicjalizowanym przez std::random_device{}()

0
didzni napisał(a):

Gdy to skompiluję g++ (MinGW-64) w Windows, to za każdym odpaleniem programu mam te same wyniki. Gdy skompiluję to clangiem lub cl lub g++ w Linuxie - wyniki nie powtarzają się. Nie rozumiem tego.

Jaką wersję MinGW używasz? Co zwraca std::entropy?
Może się okazać, że twój kompilator MinGW jest na tyle stary, że jeszcze nie wspiera generatora liczb naprawdę losowych.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85494

0
kq napisał(a):

Ale on używa std::shuffle(pula.begin(), pula.end(), gen);, gdzie gen jest std::mt19937 inicjalizowanym przez std::random_device{}()

Dokładnie, po czym użył własnej (niepoprawnej) implementacji shuffle aby działać na rand(), zaś ja mu podałem pomysł użycia random_shuffle który właśnie działa na rand()

4

Najwyraźniej nie zostałem zrozumiany.
Liczby naprawdę losowe wymagają odpowiedniego sprzętu. Jako, że to nie jest zagwarantowane na każdej platformie, standard otwiera furtkę na zastąpienie radom_device czymś co jest pseudolosowe.
Jeśli radnom_device nie jest naprawdę losowe, to wtedy zwracana wartość entropii ma być zero.

Teraz implementacja MinGW, która jest portem gcc na Windows, przez długi czas nie miała poprawnie zaimplementowanego random_device.
Jeśli wierzyć raportowi https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85494 to problem ten został rozwiązany dopiero od wersji gcc 9.2 (co jest dość niedawno temu), ergo używasz MinGW, w którym ten problem nadal występuje.

Żeby się przed tym zabezpieczyć można zrobić tak (z twojego punktu widzenia to rozwiązanie jest Ok):

thread_local auto gen = []() {
    std::random_device randDev;
    return randDev.entropy() ? std::mt19937 { randDev() } : std::mt19937 { static_cast<unsigned long>(time(0)) };
};

Czyli jeśli entropia jest zerowa to wtedy użyjemy bieżącego czasu jako ziarna losowości.

1 użytkowników online, w tym zalogowanych: 0, gości: 1