Wurf mit zwei Würfeln und Statistische Auswertung



  • is umständlich, man kann auch ein couter array erstellen, also int counter[11], dann kann man mit ++counter[Würfel1+Würfel2-2] incrementieren, und nach 6000maligem Ablauf dann auch Ausgeben, indem man eine for-Schleife einsetzt:

    ...
    for (int i = 0; i < 6000; i++){
        wuerfel1 = rand()/6+1;
        wuerfel2 = rand()/6+1;
        ++counter[Würfel1+Würfel2-2];
    }
    
    for (int i = 2; i <= 12; i++)
        cout << "Das Ergebnis " << i << " wurde " << counter[i-2] << "mal erreicht." << endl;
    

    Warum an wirklich zwei Würfel nehmen muss, und nicht einfach Eine zufallszahl von zwei bis 12 wählen kann, sieht man, wenn man einmal die Statistik wirklich auswertet, am besten sogar Graphisch: Es kommt dann viel häufiger vor eine sieben zu würfeln, als zum Beispiel eine Zwölf gewürfelt wird, denn dafür gibt es auch viel mehr Möglichkeiten.



  • ähm krux.. ich versteh deinen Ansatz grad überhaupt nicht? wieso setzt du i von 1-12 wonach ja i dem Würfelergebnis der 2 Würfel entspräche?

    for (int i = 2; i <= 12; i++)
    


  • ThaRealMatix schrieb:

    Meint ihr es wäre für dieses Programm, mit der Satistik besser 2 Einzelwürfel oder halt ne zufallzahl von 2-12 erstellen zu lassen?

    Hallo Gunnar,

    es ist nicht dasselbe, ob Du eine gleich-verteilte (!) Zufallszahl zwischen 2 und 12 generierst oder die Summe zweier Zufallszahlen von 1 bis 6. Für letzeres gibt es 36 verschieden Möglichkeiten:

    | 1  2  3  4  5  6
    --|----------------- 
    1 | 2  3  4  5  6  7
    2 | 3  4  5  6  7  8
    3 | 4  5  6  7  8  9
    4 | 5  6  7  8  9 10
    5 | 6  7  8  9 10 11
    6 | 7  8  9 10 11 12
    

    D.h. bei z.B. 396 Würfen von zwei Würfeln hat man im Mittel 11mal eine 2 (1er-Pasch) aber 66mal eine 7. Bei der gleichen Menge von Aufrufen einer Zufallszahl im Intervall [2,12] kommt die 2 und die 7 36mal - also gleich oft vor.
    Mit einer Zufalls-Zahl erhält man eine gleichförmige (uniform) Verteilung und mit der Summe zweier Zufalls-Zahlen eine symmetrische Dreiecksverteilung (triangle distribution). siehe auch http://www.boost.org/libs/random/index.html

    Gruß
    Werner



  • Hallo TheRealMatrix,

    für einen Würfel gab's das vor etwa einem Halben Jahr mal von Erhard Henkes.

    Hoffe das hilft Dir weiter

    Viele Grüße
    Knecht



  • Hm...

    okay... danke Euch allen erstmal bis hierher 🙂

    Wenn ich das nun alles so durchsehe, scheint das von T0bi für mich (bezogen auf meinen Wissensstand) die beste Lösung.

    Ich schätze mal, dass es auch der praktikabelste Weg ist, das ganze mit einer for schleife 6000 zu simulieren, man müsste halt eine schleife generieren die die Sümme der beiden Würfe wieder auf null setzt nach dem Wurf und neu würfeln lassen.

    Aber was ich nicht weiss, ist wie ich die Zufallstabelle machen soll. Man könnte ja die 11 Ergebnisse (2-12) jeweils einmal definieren und dann hochzählen lassen, wenn Sie erreicht werden

    also sinngemäß

    if (summe ==12)
    total12++
    

    Das müsste ja gehen, oder? Aber ich würde mal meinen der Code wird ziemlich lang und ineffizient?



  • Pack dir die möglichen Ergebniss besser in ein Array, dann kannst du über den Index darauf zugreifen (wie das gemacht wird, kannst du in Krux' Beitrag sehen - die '-2' dient dazu, den Wertebereich 2..12 auf den für Arrays üblichen Index-Bereich 0..10 umzurechnen).



  • Hm...

    okay

    also wäre mein code nun:

    #include <ctime>
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int wuerfel1;
    	int wuerfel2;
    	int counter[11];
    
    	srand( time( 0 ) );
    
    	for (int i = 0; i < 6000; i++)
    	{
    		wuerfel1 = rand()/6+1;
    		wuerfel2 = rand()/6+1;
    		++counter[wuerfel1+wuerfel2-2];
    	}
    	for (int i = 2; i <= 12; i++)
    	{
    		cout << "Das Ergebnis " << i << " wurde " << counter[i-2] << "mal erreicht." << endl;
    	}
    }
    

    Was aber nun dazu führt das das Program mit

    Wuerfel.exe hat ein Problem festgestellt und muss beendet werden.

    crasht

    Und wenn ich

    wuerfel1 = rand()%6+1;
    wuerfel2 = rand()%6+1;
    

    nutze wird alles negativ oft erreicht. Aber i ist doch mit 2 initialisiert?



  • Du willst nicht durch 6 teilen sonder den "Rest" haben. Du musst also das "/" durch den Modolo-Operator "%" ersetzen.

    [EDIT]Und in deiner zweiten schleife läufts Du über das ende dess arrays hinaus. Da Dein Array nur 11 Stellen groß ist darf Dein Index maximal 10 werden.



  • uhm sorry versteh ich grad nicht? was soll ich ändern 😮



  • Erstmal solltest du jeweils rand()%6+1 verwenden, dann bleibst du auch im normalen Index-Bereich. Und dann wäre es eventuell eine gute Idee, das Array vor der ersten Schleife mit Nullen zu initialisieren (am einfachsten geht das in der Initialisierung: int counter[11]={0};

    Knecht schrieb:

    [EDIT]Und in deiner zweiten schleife läufts Du über das ende dess arrays hinaus. Da Dein Array nur 11 Stellen groß ist darf Dein Index maximal 10 werden.

    Ne, die Indizes stimmen schon - der letzte Schleifendurchlauf greift auf counter[12-2] == counter[10] zu.



  • Sorry, das hab ich übersehen...



  • er meint, das deine zweite for-Schleife inakzeptabel ist da du das array
    counter ja nur mit 11plätzen deklariert hast. also:

    int counter[11], ist speicherplatz fuer 11 integral variablen.
    es soll so ablaufen das du die vorkommenden ereignisse so speicherst:

    counter[0] // beinhaltet den zählerstand für die 2er
    counter[1] // beinhaltet den zählerstand für die 3er
    counter[2] // beinhaltet den zählerstand für die 4er
    counter[3] // beinhaltet den zählerstand für die 5er
    ...
    counter[10] // beinhaltet den zählerstand für die 12er

    nun hast du deine ereignisse in das array gepackt. die zahl in den eckigen klammern beinhaltet den index also das "i" um nun in einer for-schleife alle positionen im array an zu sprechen setzt du i = 0, da das erste arrayelement immer array[0] ist. dann erhöhst du es immer um eins, dabei musst du achten das du bei der bedingung in der schleife i < 11 setzt da sonst im fremden speicher gelesen wird, dies hat die folge das dein prog abraucht.

    also sieht die schleife so aus:

    for( vereinbarung einer variablen; bedingung; was mit der variablen gemacht
    werden soll ) {

    anweisungen!
    }

    for( int i = 0; i < 11; ++i ) {
    
        cout << array[i] << endl;
    }
    

    ich hoffe es ist einigermassen richtig was ich hier jetzt geschrieben habe.

    Gruß Tobi :xmas1:



  • ahhh zu spät :D, aber hier haste mal nen prog des funzt ^^

    #include <ctime>
    #include <iomanip>
    #include <iostream>
        using namespace std;
    
    #pragma hdrstop
    #pragma argsused
    
    int main(int argc, char* argv[]) {
    
        int ereigniss[11] = { 0 };
        int wuerfel_1 = 0, wuerfel_2 = 0;
        const int loop = 6000;
    
        srand( time( 0 ) );
        for( int l = 0; l < loop; ++l ) {
    
            wuerfel_1 = rand() % 6 + 1;
            wuerfel_2 = rand() % 6 + 1;
    
            ++ereigniss[ (wuerfel_1 + wuerfel_2) - 2 ];
        }
    
        cout << " Auswertung der 6000 Wuerfe, die Zahlen 2 - 12 kamen jeweils,\n"
             << endl;
        for( int i = 0; i < 11; ++i ) {
    
            cout << " Zahl[" <<  setw( 2 ) << (i + 2) << "] = "
                 << setw( 4 ) << ereigniss[i] << "    vor." << endl;
        }
        getchar();
        return 0;
    }
    

    Gruß Tobi :xmas2:



  • #include <ctime>
    #include <cmath>
    #include <iomanip>
    #include <iostream>
    #include <conio.h>
    using namespace std;
    
    int main() 
    {
        int ereignis[11] = { 0 };
        int wuerfel_1 = 0, wuerfel_2 = 0;
    
        int LOOP;
        cout << "Wieviele Versuche? ";
        cin >> LOOP;
    
        srand( time( 0 ) );
    
        for( int l = 0; l < LOOP; ++l ) 
        {
            wuerfel_1 = rand() % 6 + 1;
            wuerfel_2 = rand() % 6 + 1;
            ++ereignis[ (wuerfel_1 + wuerfel_2) - 2 ];
        }
    
        cout << "\nAuswertung der " << LOOP << " Wuerfe. Die Zahlen 2 - 12 kamen\n" << endl;
    
        for( int i = 0; i < 11; ++i ) 
        {
            cout << " Zahl[" <<  setw( 2 ) << (i + 2) << "] = "
                 << setw( log(LOOP)/2.0 ) << ereignis[i] << " vor." << endl;
        }
    
        getch();
    }
    


  • Also, warum du negative Zahlen bekommst, liegt daran, dass deine Array-Elemente nicht initialisiert wurden, was offensichtlich zu Problemen führt.
    Da ich noch nicht so lang C++ programmiere, weiß ich allerdings nicht warum.
    Könnte mir das jemand erklären?

    Jedenfalls ist der springende Punkt (wie auch zuvor gepostet wurde):

    int array[11] = {0};

    damit werden alle Elemente des Arrays mit 0 initialisiert - keine negativen Zahlen mehr!


Anmelden zum Antworten