Zufallszahl generieren.



  • volkard schrieb:

    Jo, sobald rand nicht mehr reicht.

    Also immer.

    Ich glaube ihr würdet rand auch benutzen, wenn das so implementiert wäre:

    int rand() { return 42; }
    

    Liefert ja auch eine zufällig ausgewählte Zahl.



  • Das Problem ist doch eher, dass es in C++ keine Funktion gibt, um direkt eine gleichverteilte Zufallszahl (Ganz- oder Fliesskommazahl) in einem beliebigen Intervall zu erzeugen. Man muss dazu jeweils die Distributions und Engines nehmen, teilweise braucht man sie aber gar nicht. Für C++14 wurde daher auch std::pick_a_number() vorgeschlagen.

    rand() % anzahl hat den entscheidenden Nachteil, dass die Gleichverteilung kaputt ist. Da könnte rand() selbst noch so gut implementiert sein.



  • TyRoXx schrieb:

    volkard schrieb:

    Jo, sobald rand nicht mehr reicht.

    Also immer.

    Also fast nie.



  • Nexus schrieb:

    rand() % anzahl hat den entscheidenden Nachteil, dass die Gleichverteilung kaputt ist. Da könnte rand() selbst noch so gut implementiert sein.

    Dieser "entscheidende" Nachteil hat bei mir noch nie dazu geführt, daß der Benutzer den "Zufall" vorhersehen konnte oder daß die Monster eine sichtbare Tendenz dazu hatten, sich am linken Bildschirmrand aufzuhalten.



  • Nexus schrieb:

    Das Problem ist doch eher, dass es in C++ keine Funktion gibt, um direkt eine gleichverteilte Zufallszahl (Ganz- oder Fliesskommazahl) in einem beliebigen Intervall zu erzeugen. Man muss dazu jeweils die Distributions und Engines nehmen, teilweise braucht man sie aber gar nicht. Für C++14 wurde daher auch std::pick_a_number() vorgeschlagen.

    So etwas gehört nicht in den Standard. Die Bandbreite der möglichen Implementationen so einer Funktion würde dazu führen, dass sie für jeden speziellen Zweck nutzlos wäre.
    Es gibt diese Möglichkeiten:
    - Naiv wie rand . Schnelle, aber nutzlose Ergebnisse.
    - Mit Pseudozufall wie zum Beispiel Mersenne-Twister. Der Standard wird den Algorithmus nicht vorschreiben. Je nach tatsächlich verwendetem Algorithmus kann das zu langsam werden für viele Anwendungen. Der Punkt ist, dass ich als Benutzer keine Ahnung habe wie lange die Funktion auf der CPU herumeiern könnte. -> Energieverschwendung.
    - Zufall. Benötigt einen Systemaufruf oder eine spezielle Hardware-Instruktion. Der Systemaufruf kann zu teuer sein. Die Instruktion kann Marke NSA sein und die meisten Prozessoren haben die noch gar nicht.

    Es gibt keinen universellen Zufallsgenerator. In jedem wichtigen Programm wird diese Funktion also von vornherein verboten sein und man wird bewusst die Algorithmen je nach Anforderung wählen. In einer Hobby-Spielerei kann man sich die Funktion einfach selbst zusammenkloppen.

    Das Implementierungsbeispiel im Proposal ist obendrein auch noch falsch, weil nicht threadsafe.
    Selbst bei korrekter Implementierung würde der globale Pseudozufallsgenerator zu sicherheitsrelevanten Defekten führen. Implementierung A liefert Zufall; Programmierer verlassen sich darauf; Programmierer machen Crypto damit; Implementierung B liefert Pseudozufall; Programmierer portieren 1:1 von A nach B; fail.



  • TyRoXx schrieb:

    - Mit Pseudozufall wie Mersenne-Twister. Je nach verwendetem Algorithmus kann das zu langsam werden für viele Anwendungen. Der Punkt ist, dass ich als Benutzer keine Ahnung habe wie lange die Funktion auf der CPU herumeiern könnte. -> Energieverschwendung.

    Was heisst hier "je nach verwendetem Algorithmus"? Der Algorithmus für den Mersenne-Twister ist genau definiert. (Ja, die default_random_engine ist unnötig.)


  • Mod

    TyRoXx schrieb:

    - Naiv wie rand . Schnelle, aber nutzlose Ergebnisse.

    Ich habe mal das strittige Wort hervor gehoben. rand ist nicht nutzlos. rand ist für alle Anwendungen ausreichend, bei denen der Programmierer sich nicht mit den Feinheiten von Zufallszahlgeneratoren auseinander setzt. Und das ist der überwiegende Teil. Du bist da vielleicht einem falschen Bias ausgesetzt, wenn du im Bereich des wissenschaftlichen Rechnens oder der Kryptografie tätig bist. Wer keine Ahnung von PRNGs hat, für den ist rand (und auch die modulo-Methode) absolut ausreichend. Ein nutzerfreundlicheres Interface für eine solche Funktionalität ist durchaus zu begrüßen.



  • falls noch nicht erwähnt/bekannt:
    http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

    müsste aber eigentlich klar sein...



  • Wieso bekomme ich immer im Algorithmus die Zahlen ausgegeben?
    Das Programm soll mir aber die zahl nicht ausgeben sondern nur speichern.
    Kann ich der generierten Zahl eine Variable geben? Kann ich bei einer bestimmten Zahl einen Text ausgeben lassen? Wenn ja wie? 🙂

    Edit:

    #include <iostream>
    #include <time.h>
    
    using namespace std;
    
    int main() {
    int eingabe, ausgabe;
    time_t t;
    
    start:
    time(&t);                   // Das habe ich aus dem Internet genommen.
    srand((unsigned int)t);     // Kann mir jemand erklären was es sicht mit time(&t) und ((unsigned int)t) auf sich hat?
    
        cout << "\n\tSchere Stein Papier Spiel" << endl << endl
             << " Gib an: Schere = 1, Stein = 2, Papier = 3" << endl <<endl;
        cin >> eingabe;
        system("cls");
        cout << "\n\tSchere Stein Papier Spiel" << endl << endl
             << " Gib an: Schere = 1, Stein = 2, Papier = 3" << endl <<endl;
        ausgabe = rand()%3+1;
    
        switch ( eingabe )                              // Switch für Eingabe
        {
        case 1 :
             cout << "\n Schere" << endl;
             break;
        case 2 :
             cout << "\n Stein" << endl;
             break;
        case 3 :
             cout << "\n Papier" << endl;
             break;
        }    
        _sleep(2000);
    
        switch ( ausgabe )                             // Switch für Ausgabe
        {
        case 1 :
             cout << "\n Schere" << endl << endl;
             break;
        case 2 :
             cout << "\n Stein" << endl << endl;
             break;
        case 3 :
             cout << "\n Papier" << endl << endl;
             break;
        }               
        _sleep(2000);
    
        switch ( eingabe )                             // Switch für Text Ausgabe
        {
        case 1 :
    
             if ( eingabe == 1, ausgabe == 1 )
        {
             cout << "Schere schneidet Schere, Unentschieden" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }
        if ( eingabe == 1, ausgabe == 2 )
        {
             cout << "Stein schlaegt Schere, Verloren" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }
        if ( eingabe == 1, ausgabe == 3 )
        {
             cout << "Schere schneidet Papier, Gewonnen!" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }
             break;
    
        case 2 :
    
             if ( eingabe == 2, ausgabe == 1 )
        {
             cout << "Stein schlaegt Schere, Gewonnen!" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }
        if ( eingabe == 2, ausgabe == 2 )
        {
             cout << "Stein schlaegt Stein, Unentschieden" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }
        if ( eingabe == 2, ausgabe == 3 )
        {
             cout << "Papier umwickelt Stein, Verloren" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }
    
             break;
    
        case 3 :
    
        if ( eingabe == 3, ausgabe == 1 )
        {
             cout << "Schere schneidet Papier, Verloren" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }
        if ( eingabe == 3, ausgabe == 2 )
        {
             cout << "Papier umwickelt Stein, Gewonnen!" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }        
        if ( eingabe == 3, ausgabe == 3 )
        {
             cout << "Stein schlaegt Stein, Unentschieden" << endl << endl;
             system("PAUSE");
             system("cls");
             goto start;
        }                 
             break;
        }
    
        system("PAUSE");
        return 0;
    }
    

    Ist es zu umständlich? Geht es kürzer? Ich wollte das mein die Eingabe in der Konsole nicht sieht, geht das auch anders? Ich weis jetzt werden sich einige wieder aufregen das ich goto benutzt habe ^^ Und im Script steht auch meine 2te Frage.

    Ansonsten hat das Programm alles erfüllt was ich wollte.



  • Chechen65 schrieb:

    Wieso bekomme ich immer im Algorithmus die Zahlen ausgegeben?
    Das Programm soll mir aber die zahl nicht ausgeben sondern nur speichern.

    Dann gib sie doch nicht aus...

    Chechen65 schrieb:

    Kann ich der generierten Zahl eine Variable geben? Kann ich bei einer bestimmten Zahl einen Text ausgeben lassen? Wenn ja wie? 🙂

    Das sind absolute C++-Basics. Du solltest lieber ein gutes C++-Buch lesen, das solche grundlegenden Dinge erklärt.

    Die Funktionen std::srand() und std::time() kannst du auf einer C++-Referenzseite wie www.cppreference.com nachschlagen.

    Und ich würde keinen Code aus dem Internet kopieren, gerade wenn er so schlecht ist ( goto , lauter plattformabhängige Funktionen, enorme Codeduplikation).



  • Chechen65 schrieb:

    Ich weis jetzt werden sich einige wieder aufregen das ich goto benutzt habe ^^

    Das Ding ist, While-Schleifen, Goto-Konstrukte, Rekursion und For-Schleifen mit veränderbarer Laufvariable sind alle 3 gleichmächtig im Sinne von Berechenbarkeit. Semantisch ist es demnach egal was du nutzt. Die Frage ist, was besser lesbar und klarer von der Bedeutung ist. Und da rangiert Goto eindeutig ganz am Schluss. Zumal eine Schleife um das Programm zu packen mit einer Bool'schen Variable nicht wirklich aufwendig ist.

    Chechen65 schrieb:

    Und im Script steht auch meine 2te Frage.

    Du sagst immer Script. Das ist C/C++, das ist eine Programmiersprache und keine Scriptsprache. Und das was du da meinst ist der Quellcode (oder Sourcecode auf englisch) und kein Script (was sowas ist wie eine Mitschrit z.B. als Gedankenstütze oder als Vorlesungsmitschrift).

    Chechen65 schrieb:

    Ansonsten hat das Programm alles erfüllt was ich wollte.

    Und ist ungefähr so erweiter- und anpassbar wie 20 Meter Feldweg 😉



  • Skym0sh0 schrieb:

    Chechen65 schrieb:

    Ich weis jetzt werden sich einige wieder aufregen das ich goto benutzt habe ^^

    Das Ding ist, While-Schleifen, Goto-Konstrukte, Rekursion und For-Schleifen mit veränderbarer Laufvariable sind alle 3 gleichmächtig im Sinne von Berechenbarkeit. Semantisch ist es demnach egal was du nutzt. Die Frage ist, was besser lesbar und klarer von der Bedeutung ist. Und da rangiert Goto eindeutig ganz am Schluss. Zumal eine Schleife um das Programm zu packen mit einer Bool'schen Variable nicht wirklich aufwendig ist.

    Falsch.

    goto und while-schleife mit künstlicher Variablen halten sich hier die Waage in Sachen Schlechtigkeit.
    goto: Nachteilig ist, daß man nicht gleich oben schon sieht, daß es nur eine schlichte Schleife wird.
    while-schleife mit künstlicher Variablen: Nachteilig ist, daß das Stoppen und das Gestopp-Werden so weit auseinander liegen.

    Oft ist über eine Endlosschleife mit bedingtem break oder besser return nachzudenken, da sind auslösende if-Bedingung und knallhartes return fein beisammen.

    Der vorliegende Code ist nur deswegen goto-gräßlich, weil an sage und schreibe neun Stellen hochgesprungen wird, und dann auch noch an die falsche Stelle.

    Chechen65 sollte ein Buch lesen, gar zu viele Fehler.



  • Skym0sh0 schrieb:

    Du sagst immer Script. Das ist C/C++, das ist eine Programmiersprache und keine Scriptsprache.

    C/C++ sind sogar zwei Programmiersprachen.

    Skym0sh0 schrieb:

    Und das was du da meinst ist der Quellcode (oder Sourcecode auf englisch) und kein Script (was sowas ist wie eine Mitschrit z.B. als Gedankenstütze oder als Vorlesungsmitschrift).

    Du weißt sehr wohl, was ein Skript ist. http://de.wikipedia.org/wiki/Skriptsprache

    Chechen65 schrieb:

    Ansonsten hat das Programm alles erfüllt was ich wollte.

    Erstaunlich, denn die Spielmechanik ist total falsch.



  • Anstatt mir einfach zusagen das das falsch ist, kannst du mir sagen was ich falsch gemacht habe, und gegebenenfalls es richtig nochmal hinschreiben 🙂 Das hilft mir mehr.

    Ich habe mir dieses Buch gekauft http://www.amazon.de/C-Objektorientiertes-Programmieren-von-Anfang/dp/3499600773/ref=sr_1_1?ie=UTF8&qid=1395495783&sr=8-1&keywords=c%2B%2B+buch



  • Chechen65 schrieb:

    Anstatt mir einfach zusagen das das falsch ist, kannst du mir sagen was ich falsch gemacht habe, und gegebenenfalls es richtig nochmal hinschreiben 🙂 Das hilft mir mehr.

    Nein. Der Entwurf ist schlimmer als der Kommaoperator. Du brauchst zuerst ein wenig mehr Übersicht, würde ich sagen.

    Chechen65 schrieb:

    Ich habe mir dieses Buch gekauft http://www.amazon.de/C-Objektorientiertes-Programmieren-von-Anfang/dp/3499600773/ref=sr_1_1?ie=UTF8&qid=1395495783&sr=8-1&keywords=c%2B%2B+buch

    Das war ein gutes Buch (vor 15 Jahren. Ist aber immer noch besser als so manch anderes).



  • volkard schrieb:

    Skym0sh0 schrieb:

    Chechen65 schrieb:

    Ich weis jetzt werden sich einige wieder aufregen das ich goto benutzt habe ^^

    Das Ding ist, While-Schleifen, Goto-Konstrukte, Rekursion und For-Schleifen mit veränderbarer Laufvariable sind alle 3 gleichmächtig im Sinne von Berechenbarkeit. Semantisch ist es demnach egal was du nutzt. Die Frage ist, was besser lesbar und klarer von der Bedeutung ist. Und da rangiert Goto eindeutig ganz am Schluss. Zumal eine Schleife um das Programm zu packen mit einer Bool'schen Variable nicht wirklich aufwendig ist.

    Falsch.

    goto und while-schleife mit künstlicher Variablen halten sich hier die Waage in Sachen Schlechtigkeit.
    goto: Nachteilig ist, daß man nicht gleich oben schon sieht, daß es nur eine schlichte Schleife wird.
    while-schleife mit künstlicher Variablen: Nachteilig ist, daß das Stoppen und das Gestopp-Werden so weit auseinander liegen.

    Oft ist über eine Endlosschleife mit bedingtem break oder besser return nachzudenken, da sind auslösende if-Bedingung und knallhartes return fein beisammen.

    Sagen wir das mal so, mir wurde beigebracht bzw. ich habe mir dogmatisch angeeignet goto zu meiden; es gibt ja auch keinen Grund es zu nutzen. Das stammt vor allem aus einer Zeit, wo man mit goto noch überall hinspringen konnte.

    Dann: Egal was ist, while + boolsche Variable sieht schonmal weiter besser aus als goto. Endloswhile (oder for-ever) mit bedingtem break/return ist nochmal besser.
    Aber noch besser finde ich, wenn z.b. so Dinge wie Bedingungsprüfungen in externe Funktionen/Methoden ausgelagert werden.
    Und dabei könnte man noch erwähnen, dass größere Schleifen, wo es durch gotos, oder Abbruchbedingungen zu schlechter Lesbarkeit kommt, dann doch lieber in mehrere Funktionen aufgesplittet gehören.

    So Codemetriken wie die zyklomatische Komplexität und sowas bewerten sowas öfters ganz gut, wie ich finde.



  • Skym0sh0 schrieb:

    Sagen wir das mal so, mir wurde beigebracht bzw. ich habe mir dogmatisch angeeignet goto zu meiden;

    Ok, ein Dogma.

    Skym0sh0 schrieb:

    Dann: Egal was ist, while + boolsche Variable sieht schonmal weiter besser aus als goto.

    Und Du bist sein Prophet, hihi.

    Skym0sh0 schrieb:

    Aber noch besser finde ich, wenn z.b. so Dinge wie Bedingungsprüfungen in externe Funktionen/Methoden ausgelagert werden.

    Tja, die Anzahl 3 ist immer komisch. Mag man 3 Aufrufe zur Schleife machen oder lieber 3 Aufrufe haben? Mag man eine Funktion aufrufen, die 3 Werte zurückgeben kann und dann die 3 Fälle wieder auseinanderklamüsern?

    Skym0sh0 schrieb:

    Und dabei könnte man noch erwähnen, dass größere Schleifen, wo es durch gotos, oder Abbruchbedingungen zu schlechter Lesbarkeit kommt, dann doch lieber in mehrere Funktionen aufgesplittet gehören.

    Jo, goto und künstliche Abbruch- oder Ergebnisvariable oder break sind supi oft ein Zeichen dafür, daß diese Schleife in eine eigene Funktion gehört und dann ein schlichtes return diese ganzen Verrenkungen völlig überflüssig macht.

    Skym0sh0 schrieb:

    So Codemetriken wie die zyklomatische Komplexität und sowas bewerten sowas öfters ganz gut, wie ich finde.

    *lach*
    Damit kannste mich jagen.


Anmelden zum Antworten