Konzeptfrage zu srand()



  • Gilder schrieb:

    Sollte ich in dem Falle srand() einmal selber initialisieren, oder diese Aufgabe dem Benutzer überlassen?



  • @Badestrand: In den meisten Fällen will man Zufall. Ich fände es besser, für deterministische Folgen eine Extrafunktion aka set_seed einzurichten. Dann kann der Nutzer diese immer noch aufrufen.



  • Randensaft schrieb:

    @Badestrand: In den meisten Fällen will man Zufall. Ich fände es besser, für deterministische Folgen eine Extrafunktion aka set_seed einzurichten. Dann kann der Nutzer diese immer noch aufrufen.

    Ich musste mal einen Bug fixen, der nur sehr selten und abhängig der von rand() produzierten Werte auftrat. Ein "Lauf" der Software, bis der Bug dann auftrat, hat aber ewig gedauert (ein paar Tage), deshalb war's ganz cool die Werte nachvollziehen zu können:

    int main()
    {
        DWORD now = GetTickCount();
        log << "Seeding with " << now << "\n";
        srand( now );
        ...
    }
    

    Trat dann ein Fehler auf, hatte man den Seed in der Logdatei und konnte den Lauf reproduzieren:

    int main()
    {
        srand( BUGGY_SEED_VALUE );
        ...
    }
    

    Auch für Tests kann's nützlich sein. Angenommen, du hast Algorithmen, die ein wenig mit Zufall arbeiten und der valide Wertebereich nicht sinnvoll weit genug eingeschränkt werden kann. Um automatisiert sicherzustellen, dass das ganze System immer noch läuft wie gedacht, produzierst du initial einfach ein paar Datensätze mit bestimmten Seed-Werten, lässt die Tests mit denselben Seed-Werten arbeiten und vergleichst die Datensätze (natürlich muss man dann neue Referenz-Datensätze generieren, wenn man die Algos ändert). War übrigens im selben Projekt.

    Seitdem hab ich's gern, wenn mir niemand an meinen Seed-Werten rum-murkst. Ein srand(time(NULL)) am Anfang kriegt der Nutzer wohl noch hin, auf ein set_seed oder irgendwas per Präprozessor-Schalter würde ich mich aber auch einlassen (nur halt nicht, dass man in Libraries wurschteln muss um das Seeden auszuschalten) 🙂



  • Gilder schrieb:

    Sollte ich in dem Falle srand() einmal selber initialisieren, oder diese Aufgabe dem Benutzer überlassen?

    definierte benutzer



  • Wenn das ein C++-Projekt ist und du g++ >= 4.3 oder Boost benutzt (für MSVC weiß ich nicht genau ob und ab wann die TR1-libs drin sind), dann solltest du den Standardzufallsgenerator in Ruhe lassen und deinen eigenen, lib-internen mit tr1::random benutzen. Damit hast du Kontrolle darüber, dass er initialisiert ist, musst bei richtiger Wahl der Verteilung nichts umwandeln und hast mit dem Mersenne Twister deutlich "zufälligere" Zahlen.



  • .filmor schrieb:

    Wenn das ein C++-Projekt ist und du g++ >= 4.3 oder Boost benutzt (für MSVC weiß ich nicht genau ob und ab wann die TR1-libs drin sind), dann solltest du den Standardzufallsgenerator in Ruhe lassen und deinen eigenen, lib-internen mit tr1::random benutzen. Damit hast du Kontrolle darüber, dass er initialisiert ist, musst bei richtiger Wahl der Verteilung nichts umwandeln und hast mit dem Mersenne Twister deutlich "zufälligere" Zahlen.

    Hä???
    Tu mal nicht so, als sei rand() kacke. mersenne ist lahm, rand() ist schnell und zufällig genug.



  • Geh mal nicht so an die Decke. rand() ist Kacke, das liegt aber nicht am verwendeten Algorithmus sondern an der Implementierung (statischer globaler Speicher und so :P). Das war auch eigentlich das, was ich sagen wollte. Einen Linearen Kongruenzgenerator hat man auch in den neuen Bibliotheken.



  • .filmor schrieb:

    rand() ist Kacke, das liegt aber nicht am verwendeten Algorithmus sondern an der Implementierung (statischer globaler Speicher und so :P)

    wo liegt das Problem? und nur weil deine implementierung von rand() kacke ist, trifft das nicht zwangsläufig allg. auf rand() zu... abgesehen von wirtschafts-simulationen o.ä. hab ich bisher noch nie probleme mit rand() gehabt...

    bb


  • Mod

    unskilled schrieb:

    .filmor schrieb:

    rand() ist Kacke, das liegt aber nicht am verwendeten Algorithmus sondern an der Implementierung (statischer globaler Speicher und so :P)

    wo liegt das Problem? und nur weil deine implementierung von rand() kacke ist, trifft das nicht zwangsläufig allg. auf rand() zu... abgesehen von wirtschafts-simulationen o.ä. hab ich bisher noch nie probleme mit rand() gehabt...

    bb

    Nenn mir eine rand() Implementierung, die keinen statischer globalen Speicher verwendet...



  • wo liegt das problem? so ist das nun mal bei deterministischen Algorithmen

    bb


  • Mod

    unskilled schrieb:

    wo liegt das problem? so ist das nun mal bei deterministischen Algorithmen

    Das ist genau das Problem, worum es hier in diesem Thread geht: Wenn es nur einen globalen Zufallsgenerator gibt, dann ist man nicht selber für den Zufallsgenerator verantwortlich, sondern ist auch auf das Wohlwollen aller anderen angewiesen, die den Generator ebenfalls verwenden. Wie soll man wissen, ob nicht in irgendeiner Subroutine irgendeiner Bibliothek ein Napp vor jedem Aufruf von rand den Zufallsgenerator mit 0 initialisiert (wenn du dieses Forum kennst, weißt du wie oft Leute vor jedem rand srand benutzen) oder ob nicht irgendwer mit die Uhrzeit als seed setzt, obwohl man selber deterministisches Verhalten will. Das eingebaute rand ist daher wirklich nur allereinfachste Programme zu gebrauchen.



  • Japp, das stimmt - aber wie oft nimmt man denn bitte Libs, die den Zufallszahlengenerator neu initialisieren?
    Und:

    vor jedem Aufruf von rand den Zufallsgenerator mit 0 initialisiert

    Weil viele(wahrscheinlich fast alle^^) Anfänger Fehler damit machen, ist die Fkt. schlecht? Ich glaube nicht...

    bb



  • Blubb.

    Er sagte Projekt, dann gehe ich erstmal davon aus, dass es sich nicht um ein monolithisches Einmal-schreiben-Programm handelt sondern vielleicht ein bisschen modular ist. Wenn du rand verwendest kannst du den Determinismus vergessen. Meines Erachtens ist jede Bibliothek für ihren eigenen Zufall verantwortlich. Ist ja nicht nur so, dass du "nur" darauf verzichten musst. Du musst auch noch jedesmal locken, nur weil du eine Zufallszahl haben willst. Das gibt eine ganz tolle Threadingperformance bzw. wunderhübsches Verhalten, wenn's irgendwo im Code vergraben ist 🙂



  • ok - da hast du wohl recht ^^



  • volkard schrieb:

    .filmor schrieb:

    Wenn das ein C++-Projekt ist und du g++ >= 4.3 oder Boost benutzt (für MSVC weiß ich nicht genau ob und ab wann die TR1-libs drin sind), dann solltest du den Standardzufallsgenerator in Ruhe lassen und deinen eigenen, lib-internen mit tr1::random benutzen. Damit hast du Kontrolle darüber, dass er initialisiert ist, musst bei richtiger Wahl der Verteilung nichts umwandeln und hast mit dem Mersenne Twister deutlich "zufälligere" Zahlen.

    Hä???
    Tu mal nicht so, als sei rand() kacke. mersenne ist lahm, rand() ist schnell und zufällig genug.

    a) ist der Mersenne Twister deutlich schneller, als lrand48 und b) woher weisst Du, ob lrand48 für das (hier nicht näher spezifizierte) Problem zufällig genug ist?



  • Tachyon schrieb:

    a) ist der Mersenne Twister deutlich schneller,

    Als ich den Mersenne Twister kennelernte, stand da was von "viermal so schnell wie rand()" und weil ich immer so neugierig bin, hatte ich es ausgemessen und er war in Wirklichkeit zweimal langsamer.

    Tachyon schrieb:

    b) woher weisst Du, ob lrand48 für das (hier nicht näher spezifizierte) Problem zufällig genug ist?

    Für was ist rand() nicht zufällig genug? Doch nur für Krypto-Dinge und kryptofest ist der Mersenne Twister auch nicht.



  • volkard schrieb:

    Tachyon schrieb:

    a) ist der Mersenne Twister deutlich schneller,

    Als ich den Mersenne Twister kennelernte, stand da was von "viermal so schnell wie rand()" und weil ich immer so neugierig bin, hatte ich es ausgemessen und er war in Wirklichkeit zweimal langsamer.

    Hmm, bei mir ist der ca. 3 mal schneller. Dafür braucht er deutlich mehr Speicher.

    volkard schrieb:

    Tachyon schrieb:

    b) woher weisst Du, ob lrand48 für das (hier nicht näher spezifizierte) Problem zufällig genug ist?

    Für was ist rand() nicht zufällig genug? Doch nur für Krypto-Dinge und kryptofest ist der Mersenne Twister auch nicht.

    Simulationen z.B. bei denen Umgebungsrauschen o.ä. simuliert wird.


Anmelden zum Antworten