Problemchen mit Zufallsgenerator ?



  • Hallo zusammen,

    Dies wird nun mein erster Thread in diesem Forum 🙂 Nun zu meinem Problem. Da ich nun Semesterferien hab und mir mal wieder langweilig war, gedachte ich mal wieder ein bischen mit C rumzuspielen. Meine Idee ist es für das Glücksspiel Roullette, welches bekanntermaßen einen negative Gewinnerwartung hat =), eine kleine Simulation zu schreiben. Die Strategie, nach der sich das Programm verhalten soll, ist folgende: Ich setze 1.Wennichgewinneisgutundichsetzewieder1. Wenn ich gewinne is gut und ich setze wieder 1. Wenn ich verliere, dann errechnet sich mein neuer Einsatz wiefolgt: Einsatz_neu = Einsatz_ alt * 2 + 1 . Man stellt nun noch ein mit wieviel kapital man startet und bei wieviel gewinn man aufhören möchte. Dann spielt das Programm so oft wie eingestellt wurde mit sich selbst Roulette und wertet dies aus. Und nun komme ich zum Problem: Meine Auswertung bringt Ergebnisse, die niemals stimmen können ^^ Wie z.b. dass bei 100000 Durchläufen nur 20 mal verloren wurde. Ich denke, dass es evtl mit dem Zufallsgenerator zusammen hängt ?

    Und noch eine allgemeine Frage: Das mit den globalen Variablen und den 2 Funktionen ist wohl nich so elegant gelöst oder? Nur ist es mir für das kleine Programm am einfachsten erschienen, es so zu lösen. Falls jemand etwas besseres weiß, darf ers gerne sagen.

    Eventuell ist ja jemand so nett und beantwortet meine Nubie Fragen 🙂 Habe auch versucht das ganze ein bischen übersichtlich zu gestalten.

    Vielen Dank schon mal für Antworten,
    Stefan

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <conio.h>
    
    // GLOBALS
    
    int kapital, einsatz, startkapital=50, starteinsatz = 1, gewinn = 50, anz_versuche = 100000;
    
    // FUNCTIONS
    
    int drehen(void);
    void spielen(int spielergebnis);
    
    // GOGO 4 MAIN
    
    int main ()
    {
        srand(time(NULL));
        int wurf;
        long anz_verloren = 0, anz_gewonnen = 0;
        kapital = startkapital; einsatz = starteinsatz;
    
        for(int i = 1; i < anz_versuche; i++){
    
        // While Schleife is ein Versuch mit der Strat zu spielen
    
        while(1){
    
            wurf=drehen();
    
            spielen(wurf);
    
               // Wenn Gewinn erreicht, wird abgebrochen und WIN Zähler erhöht
    
               if(kapital>=startkapital+gewinn){
                   anz_gewonnen++;
                   break;
               }
    
               // Wenn alle Kohle verloren ist, dann wird Zähler von Loose erhöht
    
               if(kapital==0){
                    anz_verloren++;       
                    break;
                }
            }
        }
    
        // AUSGABE !!!
    
        printf("Anzahl der Versuche: %i\n", anz_versuche);
        printf("Startkapital:        %i\n", startkapital);
        printf("gewuenschter Gewinn: %i\n", gewinn);
        printf("Anzahl WIN:          %i\n", anz_gewonnen);
        printf("Anzahl LOST:         %i\n", anz_verloren);
    
        getch();
        return(0);
    }
    
    // Die Funktion drehen "dreht" das virtuelle Roulette Rad und gibt für den Fall, dass wir gewonnen haben eine 1 ansosnten eine 0 zurück.
    // Die Warscheinlichkeit für einen Treffer ist 0.4865 und da rand() eine Zahl zwischen 0 und 32767 ausgibt, ist die Grenze bei 15942 für Warscheinlichkeit 0.4865
    
    int drehen(void){ 
        int tmp, back;
        tmp = rand();
        if(tmp <= 15942) back=1; else back=0;
        return(back);
    }
    
    // Inwiefern das nun vorteilhaft ist, hier mal bischen was von der Mainroutine auszulagern, weiß ich leider nicht =)
    // Aber um das ganze noch ein bischen übersichtlich zu halten, hab ichs mal gemacht
    
    void spielen(int spielergebnis){
    
        // Wenn gewonnen wurde
    
        if(spielergebnis==1){
            kapital+=einsatz;
            einsatz=starteinsatz;
        }
        // Wenn verloren
    
        if(spielergebnis==0){
            kapital-=einsatz;
    
            // Wenn Kohle noch ausreicht um Einsatz zu erhöhen dann ...
    
            if(kapital >= einsatz * 2 + 1){
                    einsatz = einsatz * 2 + 1;
            }
    
            // Ansonsten nimm das, was übrig ist
    
            else{
                    einsatz = kapital;
            }
    
         }
    
    }
    


  • int drehen(void)
    {
        return ((float)rand()/RAND_MAX < 0.4865);
    }
    

    spicke dein programm mal mit einigen printf(), mit denen du kritische variablen ausgibst und verfolgen kannst.



  • Hätte ich wohl noch sagen sollen 🙂 ich habe das nämlich systematisch geschrieben. Habe zuerst nur mit der Funktion drehen angefangen und habe die 100000mal durchlaufen lassen und die Auftrittswarscheinlichkeiten der einzelnen Ereignisse gezählt. Dieser Schritt war in Ordnung. Der nächste Schritt war es die Strategie zu implementieren. Dabei habe ich dann mir ein paarmal die einzelnen Schritte ausgeben lassen, war auch in Ordnung. Fehlerhaft wurde das Programm erst, als ich die äußerste FOR-Schleife hinzugefügt habe, welche dafür verantwortlich ist, dass das Programm halt 100000mal läuft....

    evtl hilfts ja weiter 🙂



  • dj9nmh schrieb:

    for(int i = 1; i < anz_versuche; i++){
    
        // While Schleife is ein Versuch mit der Strat zu spielen
    
        while(1){
           
            wurf=drehen();
    
            spielen(wurf);
       
               // Wenn Gewinn erreicht, wird abgebrochen und WIN Zähler erhöht
    
               if(kapital>=startkapital+gewinn){
                   anz_gewonnen++;
                   break;
               }
           
               // Wenn alle Kohle verloren ist, dann wird Zähler von Loose erhöht
    
               if(kapital==0){
                    anz_verloren++;      
                    break;
                }
            }
        }
    

    probier mal stattdessen:

    for(int i = 1; i < anz_versuche; i++)
        {
            wurf=drehen();
            spielen(wurf);
            if(wurf)
              anz_gewonnen++;
            else
              anz_verloren++;      
        }
    


  • Wenn ich die Änderung vornehme, dann kommen kommen die Auftrittswarscheinlichkeiten von 0 und 1 genau so verteilt, wies sein soll.

    Hab mir auch überlegt, dass wir eventuell aus dem Wertebereich von Integer rauslaufen... aber das scheint auch net der Fall zu sein, sonst hätte der Versuch eben nicht geklappt.

    Mir ist außerdem aufgefallen, wenn ich das Programm für kleine anz_versuche laufen lasse, z.B. 5 oder 10 dann gewinn ich meistens alle oder verliere alle .... da ich die Strategie hier selbst schonmal mit einer Roulette Software getestet habe, ist mir aufgefallen, dass es in circa 50% der Fälle klappt. Und da man bei Roulette ja immer Verlust macht, müsste also bei einem Einsatz von 50 und einem Gewinn von 50 eine Erfolgswarscheinlichkeit von irgendwas kleiner 50% rauskommen ....



  • Die 100000 für Anz-Versuche übersteigt die Grenze von 32768 und ist deshalb eine andere Zahl. Muß long sein.
    Vielleicht bringt rand auch negative Zahlen ????
    Schönen Gruß von O.Frie



  • So ich hab jetzt mal anz_versuche als long gemacht ^^ und die werte werden auch net negativ.

    Habe aber ne andere interessante Sache festgestellt. bin ma mit meinem quellcode auf meinen linux server hier im netzwerk und hab das ganze mal mit gcc kompiliert. Siehe da, es waren schon halbwegs ordentliche Werte. Deshalb halbwegs, weil die Winrate immer noch zwischen 0.47 und 0.52 % geschwankt haben und das bei 10000000 Versuchen.

    Mit diesem Code bin ich dann wieder auf meinen Windows PC gegangen und hab das mit dem Dev-C++ kompiliert.... Es erschien mir wieder selbiges Szenario wie zuvor.... eine winrate von 1.0 ^^

    liegt das nun am Compiler oder wie muss ich das sehen?



  • spicke deinen code mit printf() und lass dir kritische variablen ausgeben.
    somit kannst du fehlerhaftes verhalten eingrenzen.

    du solltest auch mittels srand(waskonstantes) den zufall in deinem programm wiederholbar machen, damit du selber nachverfolgen kannst, ob gewisse zufallsdatan auch zum richtigen verhalten fuehren.


Anmelden zum Antworten