QT C++ Random Zahlen / Koordinaten



  • Hab in diesem neumodischen Dinges, diesem Internetz, Internet oder so das hier gefunden:
    random_shuffle



  • @wob sagte in QT C++ Random Zahlen / Koordinaten:

    @DocShoe sagte in QT C++ Random Zahlen / Koordinaten:

    random_shuffle

    Das gibts seit C++17 nicht mehr. Nimm shuffle.

    Ah, danke. Wusste ich nicht, wir hängen bei C++11 fest.



  • @DocShoe sagte in QT C++ Random Zahlen / Koordinaten:

    Hab in diesem neumodischen Dinges, diesem Internetz, Internet oder so das hier gefunden:
    random_shuffle

    Dann solltest du da aber auch rechts den Kommentar lesen - da steht sowas wie

    (deprecated in C++14)
    (removed in C++17)



  • @wob sagte in QT C++ Random Zahlen / Koordinaten:

    @DocShoe sagte in QT C++ Random Zahlen / Koordinaten:

    Hab in diesem neumodischen Dinges, diesem Internetz, Internet oder so das hier gefunden:
    random_shuffle

    Dann solltest du da aber auch rechts den Kommentar lesen - da steht sowas wie

    (deprecated in C++14)
    (removed in C++17)

    Ich hab´s nur gefunden, nicht gelesen 😉 Bis gerade eben wusste ich nicht mal, dass es deprecated ist und ab C++17 nicht mehr zur Verfügung steht. Wollte durch meinen flapsigen Kommentar nur zum Ausdruck bringen, dass man, wenn man das Schlüsselwort schon kennt, auch mal selbst suchen kann. Das war an TE gerichtet.



  • @DocShoe sagte in QT C++ Random Zahlen / Koordinaten:

    Ich hab´s nur gefunden, nicht gelesen 😉

    Ah, ich sehe, du hast ungefähr gleichzeitig wie ich geschrieben. Ich dachte, dein erster Kommentar wäre auch meinen Kommentar bezogen gewesen. War er offenbar nicht 🙂



  • @wob

    Viele Dinge die ich als C++ Anfänger noch nicht gesehen habe.
    Zeile 5 und 6 verstehe ich, dann 9 dann sozsagen nur das durchmischen aber warum am Ende nochmal rng? Kann mir aus der C++ doku gerade nichts sinnvolles zusammenreimen.
    Aber wird die rnd Zahl jetzt in rng gespeichert?



  • @karooooo1234
    Die shuffle() Funktion braucht noch einen RNG, um Zufallszahlen für´s Mischen zu ziehen. Sie erzeugt selbst keinen, sondern erwartet, dass der Aufrufer den RNG als Parameter übergibt. Die Zufallszahl wird nicht in rng gespeichert, sondern rng wird benutzt, um die nächste Zufallszahl zu erzeugen.



  • Wie speichere ich dann die Zufallszahl in einer varibalen? Ziehe ich mir einfach raus mit
    int index = v[rng]?
    Irgendwie checke ich es einfach nicht. Langer Tag..



  • eigentlich kann ich mit bei v[1] ja dann irgendeine stelle ausgeben lassen oder?



  • @karooooo1234
    Nein, das macht shuffle für dich. Nehmen wir mal wob´s Code:

    // globaler Generator
    std::mt19937 rng(std::random_device{}());
    
    // globaler vector 
    std::vector<int> v;
    
    void start_cycle()
    {
       v.resize( 100 );
       std::iota(begin(v), end(v), 0);
       
       // durchmischen
       std::shuffle(begin(v), end(v), rng);
    }
    
    // der vector enthält jetzt alle Zahlen von 0-99 in zufälliger Reihenfolge.
    void fire()
    {
       if( v.empty() )
       {
          // der Vektor ist leer -> neuen Zyklus beginnen
          start_cycle( v );
       }
       // erstes Element benutzen
       int val = v.front();
       v.erase( v.begin() );
    
       // oder letztes Element benutzen
       int val = v.back();
       v.erase( v.rbegin() );
    
       // tu was mit val
    }
    

    Jetzt solltest du nur noch zusehen, dass du die globalen Variablen loswirst.


  • Mod

    vector::pop_back anyone? Und es gibt bestimmt einen Grund, wieso vector nur pop_back kennt, und nicht, wie manche andere Container, pop_front



  • @DocShoe sagte in QT C++ Random Zahlen / Koordinaten:

    Jetzt solltest du nur noch zusehen, dass du die globalen Variablen loswirst.

    Vielleicht mit einer Klasse?

    struct FirepointGenerator {
        FirepointGenerator(size_t n_fields) :
            v(n_fields),
            current_pos(end(v))
        {
            std::iota(begin(v), end(v), 0);
        }
    
        template <typename URBG>
        int next(URBG &rbg) {
            if (current_pos == end(v)) {
                std::shuffle(begin(v), end(v), rbg);
                current_pos = begin(v);        
            }
            return *current_pos++;
        }
    
    private:
        std::vector<size_t> v;
        std::vector<size_t>::const_iterator current_pos;
    }
    
    int main() {
        std::mt19937 rng(std::random_device{}());
        FirepointGenerator fpg(10);
        for (int i = 0; i < 25; ++i) cout << fpg.next(rng) << " ";
    }
    


  • @wob

    Ja, vielleicht. Ich wollte TE jetzt nicht alles auf´m Silbertablett servieren.
    Du solltest noch´n Test auf n_fields > 0 machen.


  • Gesperrt

    #include <random>
    
    std::random_device random_device;
    std::uniform_int_distribution<> uniform_int_distribution(min, max);
    int random_number = uniform_int_distribution(random_device);
    


  • Ich hab sowas: (?)

    	template <typename T> T createRandomReal(const T begin, const T end)
    	{
    		std::random_device rd;
    		std::mt19937 gen(rd());
    		std::uniform_real_distribution<T> rnd(begin, end);
    		return rnd(gen);
    	}
    
    	template <typename T> T createRandomInt(const T begin, const T end)
    	{
    		std::random_device rd;
    		std::mt19937 gen(rd());
    		std::uniform_int_distribution<T> rnd(begin, end);
    		return rnd(gen);
    	}
    


  • @zeropage Ständig neue random devices und -generators zu erzeugen ist sicher nicht die feine Englische Art.



  • Also lieber sowas:?

    namespace random
    {
    	std::mt19937 randomGenerator;
    
    	void setRandomDevice() // muss einmalig aufgerufen werden
    	{
    		std::random_device rd;
    		std::mt19937 gen(rd());
    		randomGenerator =  gen;
    	}
    
    	template <typename T> T createRandomReal(const T begin, const T end)
    	{
    		std::uniform_real_distribution<T> rnd(begin, end);
    		return rnd(randomGenerator);
    	}
    
    	template <typename T> T createRandomInt(const T begin, const T end)
    	{
    		std::uniform_int_distribution<T> rnd(begin, end);
    		return rnd(randomGenerator);
    	}
    }
    
    


  • @zeropage sagte in QT C++ Random Zahlen / Koordinaten:

    	std::mt19937 randomGenerator;
    
    	void setRandomDevice() // muss einmalig aufgerufen werden
    	{
    		std::random_device rd;
    		std::mt19937 gen(rd());
    		randomGenerator =  gen;
    	}
    

    Vielleicht wäre der mt19937 sogar Kandidat für ein Meyer-Singleton. (Nein, ich bin sonst generell kein riesiger Fan von Singletons.)



  • @Swordfish
    Fehlt da nicht noch zweimal static? Ansonsten generiere ich pro Aufruf zwei Instanzen von std::random_device und std::mt19937.

    std::mt19937 randomGenerator;
    
    void setRandomDevice(std::mt19937) // muss einmalig aufgerufen werden
    {
    	static std::random_device rd;
    	static std::mt19937 gen(rd());
    	randomGenerator = gen;
    }
    


  • @Quiche-Lorraine sagte in QT C++ Random Zahlen / Koordinaten:

    Fehlt da nicht noch zweimal static? Ansonsten generiere ich pro Aufruf zwei Instanzen von std::random_device und std::mt19937.

    Kann du das genauer erklären? Verstehe nicht, wozu das static bei dir gut sein soll - das setRandomDevice soll hier ja nur 1x aufgerufen werden. Wozu musst du also das rd und eine Kopie des mt19937 behalten? Und wo generierst du "pro Aufruf zwei Instanzen von std::random_device und std::mt19937"? Und warum hast du (im Gegensatz zu @Swordfish vorher) jetzt einen unbenutzten Parameter in dem setRandomDevice?

    Andererseits: ich verstehe den Vorteil dieses gesamten Codes sowieso nicht: man setzt fest mt19937 ein. Der ist zwar oftmals gut und ausreichend, aber vielleicht möchte man einen anderen Generator nutzen? Oder den mt19937 anders initialisieren? Und dann muss man sich für jede exisiterende Distribution hier jetzt eine eigene weitere Funktion mit anderem Namen merken? Also createRandomInt statt uniform_int_distribution. Ich würde gerne den Vorteil verstehen.


Anmelden zum Antworten