Zufallszahlen zwischen 1 und 500000



  • Hallo zusammen.

    Ich habe ein Problem mit Zufallszahlen.
    Ich habe einen Vektor, der von einer Datei mit Wörter versorgt wird.
    Momentan sind es um die 500.000 Stück.

    Diese sollen im Rahmen eines Spiels zufällig gezogen und ausgegeben werden.

    Ich habe nun ein Problem mit den Zufallszahlen.
    Ich habe folgendes versucht:

    zufallszahl = min+(rand() % (vektor.size()-min));
    

    Leider werden die Zahlen nie größer als 32000.

    Bis 36000 habe ich noch Wörter mit A. D.h. ich komme nie auf Wörter, die mit B oder anderen Buchstaben anfangen, weil meine Zufallszahl einfach zu klein ist, bzw. nicht weit genug streut.

    Auch eine Ausgabe direkt funktioniert nicht.

    cout << i+1 <<". Zufallswort: " << init::karten[rand() % init::karten.size()] << endl;
    

    Auch diese Referenz: http://www.cplusplus.com/reference/random/ kenn ich, leider komme ich dort nicht weiter.

    Dort habe ich auch das gefunden:
    http://www.cplusplus.com/reference/random/random_device/max/

    Ich verstehe jedoch nicht, wie ich max auf eine Zahl setzen kann, damit diese nicht überschritten wird.
    Ich habe dort schon eine Funktion gefunden, diese Zahlen übersteigen die 500.000 aber deutlich, so dass mein Vektor direkt out of range ist und das Programm abstürzt.

    Grüße



  • Nimm einfach sowas wie mt19937_64 und seede mit random_device. http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution



  • Ich schätze, dein vector hat einfach nicht so viele Elemente, wie du denkst. Gib doch beim Erzeugen jeder Zufallszahl mal vektor.size() mit aus.

    EDIT:
    http://ideone.com/YNqC7Q (Ausgabe bei mit mit dem ersten Versuch: 489898)



  • @ _matze

    Also mein Vektor hat soviele Elemente 🙂
    Die Liste ist ja auch wirklich 500000 Wörter groß.
    Lasse mir im Programm auch mit.

    Danke, werde ich auch versuchen 🙂

    init::karten.size();
    

    die Größe meines Vektors ausgeben. Der ist aktuell bei 530011 Wörtern. Das sehe ich aber auch in meiner .dic Datei.

    @cooky451

    Ich werde es mal testen. Danke.



  • Welchen Typ hat zufallszahl denn?



  • Shizophren schrieb:

    Leider werden die Zahlen nie größer als 32000.

    Viele (ältere) rand()s sind zwischen 0 und 32767.
    Also 15 Bits.
    Kannst das beheben mit zwei rand()-Aufrufen.

    int bigRand(){
       return (rand()<<15)|rand();
    }
    

    Das schiebt die 15 Bits des ersten rand()-Aufrufs um 15 Bits nach <- und tut dann noch mit | hinten noch 15 zufällige Bits mit noch einem rand()-Aufruf dran.





  • Shizophren schrieb:

    Auch diese Referenz: http://www.cplusplus.com/reference/random/ kenn ich, leider komme ich dort nicht weiter.

    Dort steht doch schon ein Beispiel das nur noch minimal modifiziert werden muss 😕

    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(1,6);
    int dice_roll = distribution(generator);  // generates number in the range 1..6
    

    Dort habe ich auch das gefunden:
    http://www.cplusplus.com/reference/random/random_device/max/

    Das Random Device ist nicht wirklich als RNG geeignet. Das spuckt zwar mehr oder weniger "echte" Zufallszahlen aus, aber dafür sind die nicht notwendigerweise gleichverteilt oder sonstwie mathematisch/statistisch betrachtet besonders "gut".

    Ich verstehe jedoch nicht, wie ich max auf eine Zahl setzen kann, damit diese nicht überschritten wird.

    Kannst du gar nicht. Erstmal ist ein Random Device wie schon gesagt eh nicht fit als RNG, und zweitens gibt es zum "Eingrenzen" der Zufallszahlen eben die Distributions.
    Die min() und max() Funktionen des Random-Device ist nur dazu da damit man den minimalen/maximalen Wert abfragen kann den das Device produzieren kann/wird.

    Fertiges Beispiel:

    #include <random>
    #include <array>
    
    int main()
    { 
    	typedef std::mt19937 my_rng_engine; // Die Engine die wir verwenden wollen
    	typedef std::random_device my_seed_device; // Das Device das wir zum Seeden der Engine verwenden wollen
    	typedef std::uniform_int_distribution<size_t> uniform_size_t_distribution; // Die distribution die wir verwenden wollen
    
    	// Seed Sequence erzeugen
    	my_seed_device seed_device;
    	std::array<my_seed_device::result_type, 4> seed_numbers = { seed_device(), seed_device(), seed_device(), seed_device() };
    	std::seed_seq seed(seed_numbers.begin(), seed_numbers.end());
    
    	// Generator erzeugen & gleichzeitig seeden
    	my_rng_engine engine(seed);
    
    	// Distribution erzeugen
    	uniform_size_t_distribution dist(0, 500000);
    
    	// Zahlen ziehen
    	for (size_t i = 0; i < 10; i++)
    		std::cout << dist(engine) << "\n";
    
    	return 0; 
    }
    

    Das Erzeugen der Seed-Sequenze geht wesentlich eleganter mit 'ner Initializer-List, aber da ich VC11 verwende (der die noch nicht "kann")...



  • Vielen Dank euch allen!

    @hustbaer das hat geholfen 👍 Vielen Dank für die ausführliche Antwort.
    Fürs nächste mal weiß ich wie es geht.
    Nicht gerade "unkompliziert" für ein paar Zufallszahlen 🙂



  • Doch, eigentlich ists nicht sehr schwer. Und es hat alles was man braucht.

    Mit rand() hat man früehr dann noch irgendwelche ranges drumgebastelt, oder man musste sich wie SeppJ beschrieben hat, ein "BigRand()" bauen. Und das ist ja keine Zauberkunst, sondern nur so Standardkram, der sich nicht ändert.

    Die STL hat das ein bisschen verallgemeinert (wies auch sein muss).

    Aber ich gebe zu, mich schreckt das auchw as ab 😉 😃


  • Mod

    Skym0sh0 schrieb:

    SeppJ

    Sicher?
    🕶



  • Für mich seid ihr beide göttergleich...
    Aber du hast Recht, du hast dich bei dem post mit deinem Namen verschrieben und hast als Pseudonym 'volkard' benutzt... 😉 😃


Anmelden zum Antworten