Zufälliges Wort / Satz ausgeben?



  • #include <iostream>
    #include <array>
    #include <string>
    #include <random>
    
    int main()
    {
    	std::random_device rd;
    	std::mt19937 gen(rd());
    	std::uniform_int_distribution<> dis(0, 5);
    
    	std::array<std::string, 6> words = {"Hallo", "Welt", "Mir", "geht", "es", "gut"};
    	std::cout << words[dis(gen)];
    
    	std::cin.get();
    }
    


  • 🙄

    Edit: Ernsthaft? Du nutzt Mersenne Twister für so etwas?



  • DerNoob schrieb:

    PS: Bitte nichts allzu kompliziertes 😞

    Die allereinfachste Variante wäre mit if bzw. switch:

    int main()
    {
        char wort1[] = {"Hallo"};
        char wort2[] = {"Welt"};
        char wort3[] = {"Mir"};
        char wort4[] = {"geht"};
        char wort5[] = {"es"};
        char wort6[] = {"gut"};
    
        srand(timeGetTime()); 
        int zahl = (rand() % 6);
    
        switch (zahl)
        {
        case 0:
            puts(wort1);
            break;
        case 1:
            puts(wort2);
            break;
        case 2:
            puts(wort3);
            break;
        case 3:
            puts(wort4);
            break;
        case 4:
            puts(wort5);
            break;
        case 5:
            puts(wort6);
            break;
        default:
            assert(0 && "darf nicht vorkommen");
        }
    }
    

    Sollte aber klar sein dass das nicht so optimal ist.
    Je mehr Wörter du hast, und je mehr Stellen du hast wo du auf diese zugreifen musst, desto unübersichtlicher wird es.

    Also packst du die Wörter in eine Liste.
    Die einfachste Variante ist ein Array mit fixer Grösse zu nehmen:

    int main()
    {
        char wort1[] = {"Hallo"};
        char wort2[] = {"Welt"};
        char wort3[] = {"Mir"}; // Grosses M?
        char wort4[] = {"geht"};
        char wort5[] = {"es"};
        char wort6[] = {"gut"};
    
        char* woerter[] = { wort1, wort2, wort3, wort4, wort5, wort6 };
        int wort_anzahl = sizeof(woerter) / sizeof(woerter[0]);
    
        srand(timeGetTime()); 
        int zahl = (rand() % wort_anzahl);
    
        puts(woerter[zahl]);
    }
    

    Und wenn du die Wort-Arrays nicht für sich alleine brauchst, dann noch kürzer so:

    int main()
    {
        char const* woerter[] = { "Hallo", "Welt", "mir", "geht", "es", "gut" };
        int wort_anzahl = sizeof(woerter) / sizeof(woerter[0]);
    
        srand(timeGetTime()); 
        int zahl = (rand() % wort_anzahl);
    
        puts(woerter[zahl]);
    }
    

    Ansonsten ist das was "out" schon richtig. Guck dir std::string und std::vector an.



  • Edit: Ernsthaft? Du nutzt Mersenne Twister für so etwas?

    Was würdest du verwenden? 🙂



  • Da die Qualität der Zufallszahlen in diesem Beispiel sowas von egal sind, std::default_random_engine. Erst wenn es auf die Qualität der Zahlen ankommt (Kryptographie oder ähnliches), wähle ich explicit einen aus.



  • Nathan schrieb:

    Da die Qualität der Zufallszahlen in diesem Beispiel sowas von egal sind, std::default_random_engine.

    Wenn die Qualität des PRNGs egal ist, wieso dann nicht einfach std::rand . Das wird meistens durch einen linearen Kongruenzgenerator implementiert. Das reicht völlig aus.



  • Ja, klar, aber wenn man komplizierter distributions nehmen will?
    OK, ich könnte std::minstnd_rand nehmen oder wie der Generator heißt, aber ich vertraue einfach mal dem Compiler. Der wird schon wissen, was er tut.
    Edit: Bei mir ist std::minstnd_rand0 sowieso default.



  • Danke an hustbaer, seine zweite Möglichkeit gefällt mir und funktioniert auch 😃

    Was gibt es denn bei Zufallszahlen für evtl. Qualitätsmängel? 😕



  • DerNoob schrieb:

    Was gibt es denn bei Zufallszahlen für evtl. Qualitätsmängel? 😕

    Einige Pseudozufallsgeneratoren haben bspw. eine kleine Periode*, oder weisen weniger Hyperebenen auf.

    Natürlich sind alle Folgen, die durch PRNGs erzeugt werden, deterministisch - also berechnet. Es geht aber darum, einen Pseudozufall zu erzeugen - also Zahlenfolgen, die zufällig wirken.

    Das tun einige Generatoren eben einfach nicht so gut wie andere.

    *Und: Nein, das ist mehr als nur eine Penislänge.


  • Mod

    Nochmal laut und deutlich: std::rand, std::default_random_engine und eigentlich jeder normale Zufallsgenerator der irgendwo angeboten wird sind mehr als ausreichend für 99.9% aller Programmierer. Die Leute, die tatsächlich auf die Qualität der Zufallszahlgeneratoren achten müssen (wissenschaftliches Rechnen, Kryptographie), wissen (hoffentlich) schon über das Thema Bescheid.



  • @SeppJ:
    std::rand ist oft aus Kompabilitätsgründen ein wirklich mieser Generator. So mies, dass es selbst beim Mischen von Karten für ein Kartenspiel schon zu seltsamen Effekten kommen kann.

    Weiters finde ich std::rand nicht gut, weil es globalen State hat.
    In Fällen wo man reproduzierbare Ergebnisse nach dem Seeden mit einer bestimmten Zahl braucht, würde ich grundsätzlich davon abraten.
    Weil man nie garantieren kann dass nicht irgend ein anderer Programmteil ebenfalls rand/srand verwendet.

    std::default_random_engine sollte für die allermeisten Sachen OK sein, wenn man die untersten 2-3 Bits verwirft.

    Nur frag' ich mich wieso man nicht gleich z.B. ranlux24 bzw. ranlux48 verwenden sollte, wenn man keine speziellen Anforderungen hat.
    Ich weiss nicht wie schnell die sind, aber "muss super schnell sein" wäre ja schon eine spezielle Anforderung.


Anmelden zum Antworten