Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Próba wylosowanie wielu liczb z zakresu bez powtórzeń

Ostatnio zmodyfikowano 2016-02-20 18:43
Autor Wiadomość
executor1909
Temat założony przez niniejszego użytkownika
Próba wylosowanie wielu liczb z zakresu bez powtórzeń
» 2016-02-20 17:52:21
Mam problem, chciałbym wylosować sporo liczb z przedziału np. <0, 3>. Aby były one nie tylko liczbami całkowitymi zrobiłem coś takiego:
C/C++
void losowanie( double * tablica, double poczatek, double koniec, int ile ) //losowanie n argumentow z wybranego przedzialu bez powtorzen
{
    double zmienna;
    bool powtorzenie;
   
    tablica[ 0 ] = poczatek; //ustawiamy sobie wartosci przedzialu
    tablica[ ile - 1 ] = koniec;
   
    for( int i = 1; i < ile - 1; ++i )
    {
        powtorzenie = false;
        zmienna = static_cast < double >( rand() % static_cast < int >( 10000 *( koniec - poczatek ) ) + static_cast < int >( 10000 * poczatek ) );
        zmienna /= 10000.0;
       
        for( int j = 0; j < ile; ++j )
        {
            if( zmienna == tablica[ j ] )
                 powtorzenie = true;
           
        }
        if( powtorzenie == false )
             tablica[ i ] = zmienna;
        else
        {
            cout << "Powtorzenie!" << endl;
            --i;
        }
    }
}
Na początku myślałem, że z dalszą częścią programu coś jest nie tak, bo raz rozwiązywanie problemu trwało kilka setnych sekundy, a czasem nawet do kilku minut. Jednak potem dodałem "cout << "Powtorzenie!" << endl" ...

Kod działa poprawnie, ale niestety przy losowaniu 100 liczb w małych przedziałach trwa to bardzo długo, a linia "Powtórzenie!" wyświetla się non stop. Jest jakiś sposób, żeby szybciej wylosować te liczby?
P-145083
Monika90
» 2016-02-20 18:09:21
Nie wiem po co Ci takie liczby, więc nie wiem jaka metoda będzie najlepsza, ale można np. tak
C/C++
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <ctime>

int main()
{
    const int min = 0;
    const int max = 3;
    const int precision = 10000;
    std::mt19937 rng( std::time( nullptr ) );
    std::vector < int > pool(( max - min ) * precision + 1 );
    std::iota( pool.begin(), pool.end(), 0 );
    std::shuffle( pool.begin(), pool.end(), rng );
    for( auto i: pool )
         std::cout <<( i + min * precision ) / static_cast < double >( precision ) << ' ';
   
}

W miarę możliwości należy użyć czegoś lepszego niż std::time(nullptr) do inicjalizacji generatora.
P-145084
executor1909
Temat założony przez niniejszego użytkownika
» 2016-02-20 18:34:55
Mam bardzo oryginalne zadanie - stworzyć coś w rodzaju wykresu funkcji dla dowolnej funkcji znając jej wzór i przedział, ale bez używania pochodnych, granic, itp. , tylko podstawowe działania ;)
Aby był on w miarę dokładny, zamierzam znaleźć jak najwięcej argumentów dla danego przedziału i obliczyć ich wartości, stąd takie liczby.

Dziękuję za odpowiedź! Z chęcią sprawdzę ten sposób.
P-145085
Monika90
» 2016-02-20 18:43:49
Drobna poprawka, tak będzie lepiej
C/C++
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <ctime>

int main()
{
    const int min = 0;
    const int max = 3;
    const int precision = 10000;
    std::mt19937 rng( std::time( nullptr ) );
    std::vector < int > pool(( max - min ) * precision + 1 );
    std::iota( pool.begin(), pool.end(), min * precision );
    std::shuffle( pool.begin(), pool.end(), rng );
    for( auto i: pool )
         std::cout << i / static_cast < double >( precision ) << ' ';
   
}
P-145087
« 1 »
  Strona 1 z 1