Liczby losowe sie powtarzają

0

Czesc,
napisalem funkcje ktora zwraca wartosc losowa z rokladu normalnego,tylko ze kiedy umieszczam ją w wektorze po przez funkcje generate z biblioteki stl to te liczby sie powtarzają i nie wiem jak to zrobic zeby były unikatowe ;<

double RandomNumber() {

    random_device rd;
    mt19937 genn(rd());
    normal_distribution<double> distribution(0, 10);
    return distribution(genn);
}
int main()

{
    vector<double> vi(3);
    generate(begin(vi), end(vi), RandomNumber);
    vector<double>::iterator it = vi.begin();
    while (it != vi.end())
    {
        cout << vi.front()<< endl;
        it++;
    }

kiedy pisze jakiegos normalnego fora i w nim wywoluje funkcje RandomNumber to liczby są różne dlatego nie wiem wlasnie czy źle pisze ten generator czy co :/

5
cout << vi.front()<< endl;

Wypisujesz za każdym razem pierwszy element wektora, więc nic dziwnego, że jest taki sam. Wystarczyło się zbędnie nie bawić w pętle z poprzedniego tysiąclecia i problemu by nie było.

Swoją drogą, random_device powinieneś użyć raz - do zaseedowania prng i to z niego korzystać, np.:

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

template<typename T>
T random(T min, T max) {
    using dist = std::conditional_t<
        std::is_integral<T>::value,
        std::uniform_int_distribution<T>,
        std::uniform_real_distribution<T>
    >;
    return dist{min, max}(gen);
}
2

A odpowiadając na Twoje pytanie: jak liczby mają udawać losowe, to się będą powtarzać, bo taka jest natura rozkładów losowych.

Ale jeśli takich powtórzeń bardzo nie chcesz, to nasuwają się trzy rozwiązania:

  1. Trzymać gdzieś kolekcję (jaką — zależy od liczby spodziewanych powtórzeń; należy wybór poprzeć wcześniejszymi testami) trzymającą już wylosowane liczby i gdy nowo wylosowana się nam trafi już z tej kolekcji, to losujemy jeszcze raz. Rozwiązanie sprawdza się głównie przy niewielkiej liczbie spodziewanych powtórzeń w porównaniu do możliwego zakresu.
  2. Zacząć od listy wartości, z której chcesz mieć rezultaty i ją potasować. Rozwiązanie zadziała wtedy, gdy lista (a zatem — zakres wartości) jest niewielki, a generator ma duży okres.
  3. Użyć wyspecjalizowanego generatora gwarantującego brak powtórzeń, np. pcg_64_once_insecure. Rozwiązanie najlepsze, ale wymaga zewnętrznych zależności.
1

Ja jeszcze dodam, że skoro korzystasz z C++11 (użycie std::mt19937 std::normal_distribution std::begin), to powinieneś skorzystać ranged-for:

for (auto x : vi)
{
    cout << x << '\n';
}

Nie używaj endl, jeśli nie musisz, bo to robi jeszcze flush, co bardzo negatywnie odbija się na wydajności.

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