Importer:Error:WasEmpty



  • Hallo, ich programmiere schon seit längerer Zeit in der Sprache "C++".
    Ich bin letztens darauf gekommen ein Programm in C++ zu schreiben der eine Schleife laufen lässt (ca. alle 50ms ein Durchlauf), und dort in jedem Durchlauf mithilfe der Zeit eine zufällige Zahl zwischen 1-10 generiert wird, dabei wird berechnet wie oft jede einzelne Zahl dran kam und wird als Prozentsatz ausgegeben (also bei 10 Zahlen sollte jede 10%tige Wahrscheinlichkeit haben).

    Ich habe das Programm ausgeführt und die Schleife genau 45000 durchlaufen lassen,
    das Ergebnis hat mich aber verblüfft und ich hoffe ihr könnt mir erklären warum das so ist oder ob ich ein Fehler gemacht habe:

    Ergebnis nach 45000 Durchläufen:

    1. Die 10 Zahlen hatten nicht alle eine Wahrscheinlichkeit von 10% dranzukommen sondern eine Wahrscheinlichkeit zwischen 5%-16%.

    2. Und das hat mich dann noch viel mehr verblüfft:
    Die prozentige Wahrscheinlichkeit das eine Zahl drankommt hat von 1 bis 10 abgenommen d.h. Die Zahl 1 hatte die höchste Wahrscheinlichkeit und die Zahl 10 die niedrigste.

    Das Ziel meines Projektes war aber zu beweisen das bei 10 zufälligen Zahlen jede Zahl eine Wahrscheinlichkeit von 10% haben müsste dranzukommen (bei 3 Zahlen 33,3% Wahrscheinlichkeit etc.).

    Ergebnisse meiner Werte -> Zahl+Wahrscheinlichkeit:
    1=16%; 2=14%; 3=13%; 4=12%; 5=11%; 6=10%; 7=10%; 8=9%; 9=7%; 10=5%;

    Bitte erklärt mir diesen Mist X.x..

    Quellcode des C++-programmieren Programms:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <iostream>
    #include <windows.h>
    
    using namespace std;
    
    int main()
    {
    
      int i;
      time_t t;
      time(&t);
      srand((unsigned int)t);              
    
      float n1 = 0;
      float n2 = 0;
      float n3 = 0;
      float n4 = 0;
      float n5 = 0;
      float n6 = 0;
      float n7 = 0;
      float n8 = 0;
      float n9 = 0;
      float n10 = 0;
      int Zähler = 0;
    
      while (true)
      {
    	  Zähler++;
    
    	  if (rand() % 10 == 0) n1++;
    	  else if (rand() % 10 == 1) n2++;
    	  else if (rand() % 10 == 2) n3++;
    	  else if (rand() % 10 == 3) n4++;
    	  else if (rand() % 10 == 4) n5++;
    	  else if (rand() % 10 == 5) n6++;
    	  else if (rand() % 10 == 6) n7++;
    	  else if (rand() % 10 == 7) n8++;
    	  else if (rand() % 10 == 8) n9++;
    	  else if (rand() % 10 == 9) n10++;
    	  else Zähler--;
    
    	  cout << "Zufallszahlen Wahrscheinlichkeitsberechner (von 1-10):\n\n";
    	  cout << "Zaehler: " << Zähler << "\n\n";
    	  cout << "Zahl 1: " << n1 << " = " << n1/Zähler*100 << "%\n\n";
    	  cout << "Zahl 2: " << n2 << " = " << n2/Zähler*100 << "%\n\n";
    	  cout << "Zahl 3: " << n3 << " = " << n3/Zähler*100 << "%\n\n";
    	  cout << "Zahl 4: " << n4 << " = " << n4/Zähler*100 << "%\n\n";
    	  cout << "Zahl 5: " << n5 << " = " << n5/Zähler*100 << "%\n\n";
    	  cout << "Zahl 6: " << n6 << " = " << n6/Zähler*100 << "%\n\n";
    	  cout << "Zahl 7: " << n7 << " = " << n7/Zähler*100 << "%\n\n";
    	  cout << "Zahl 8: " << n8 << " = " << n8/Zähler*100 << "%\n\n";
    	  cout << "Zahl 9: " << n9 << " = " << n9/Zähler*100 << "%\n\n";
    	  cout << "Zahl 10: " << n10 << " = " << n10/Zähler*100 << "%\n\n";
    
          system("CLS");
      } 
    
      cout << "\n\n\n";
      system("PAUSE");
      return 0;
    }
    

    MFG Moorky! 🙂


  • Mod

    Du musst einmal eine Zahl ziehen, nicht in jeder Abfrage eine neue.



  • ausserdem ist es keine gleichverteilung wenn du mit dem modulooperator arbeitest



  • 1. Ich habe die else if befehle jetzt durch einfache if befehle ersetzt und jede gibt es nichtmehr diese 1-10 abnehmende Wahrscheinlichkeit 😃

    2. Was meinst du mit Moduloperator?

    Also:

    if (rand() % 10 == 0) n1++;
    	  if (rand() % 10 == 1) n2++;
    	  if (rand() % 10 == 2) n3++;
    	  if (rand() % 10 == 3) n4++;
    	  if (rand() % 10 == 4) n5++;
    	  if (rand() % 10 == 5) n6++;
    	  if (rand() % 10 == 6) n7++;
    	  if (rand() % 10 == 7) n8++;
    	  if (rand() % 10 == 8) n9++;
    	  if (rand() % 10 == 9) n10++;
    	  if (rand() % 10 > 9 && rand() % 10 < 0) Zähler--;
    


  • Moorky Dragonstrike schrieb:

    1. Ich habe die else if befehle jetzt durch einfache if befehle ersetzt und jede gibt es nichtmehr diese 1-10 abnehmende Wahrscheinlichkeit 😃

    wieso hast du das gemacht und nicht einfach den rat von seppj befolgt?

    Moorky Dragonstrike schrieb:

    2. Was meinst du mit Moduloperator?

    moduloperator habe ich nie geschrieben, schau genauer hin. und wenn du den modulooperator selbst verwendest ohne es zu wissen dann tippe ich eher auf kopierten code.


  • Mod

    Hier eine etwas "bessere" Lösung zum Abschreiben:
    http://ideone.com/aG3u7N

    Wie du siehst, in wesentlich weniger Code, durch Anwendung einfacher Kontrollstukturen.

    @asdfasdf: Übertreib mal nicht. Schätz mal ab, wie viele Versuche du machen musst, um festzustellen, dass das nicht gleichverteilt ist. Das ist gleichverteilt genug für praktisch jeden Zweck. Erst wenn die Zahl unterschiedlicher Zahlen ein signifikanter Teil von RAND_MAX wird (und keine Zweierpotenz ist), sollte man sich so langsam Sorgen machen. Bei 10 ist das sicher nicht relevant. Auch nicht bei 100 oder 1000. (Bei 10000 allerdings schon, wenn RAND_MAX nur 2 hoch 15 sein sollte)



  • Wenn man viele gleichartige Variablen hat, die sich sogar nur in (fortlaufenden) Ziffern unterscheiden, sollte man zu einem Array greifen.

    Zum zaehlen sind float-Variablen ungeeignet.

    Was soll das else Zaehler--; ? Welcher Fall soll da denn eintreten?
    Und Umlaute in Bezeichnern sind auch nicht gut. (Hier kein Umlaut, wegen Vorschau-Bug)

    unsigned n[10] = {0};
    
    ...
      for (int Zaehler= 0; Zaehler< 45000; Zaehler++)
      {
        n[rand() % 10]++;
        for(int i = 0;i<10;i++}
          cout << "Zahl " << i << ": " << n[i] << " = " << n[i]*100.0/Zaehler<< "%\n\n"; // Reihenfolge beim rechnen beachten, wegen Integerdivision
      }
    


  • Der Code ist generell schrecklich unübersichtlich und völlig unnötig lang. Mach dir ein Array und benutze die Zufallszahl als Index. Am besten nimmst du auch <random> da bekommst du gleich die gewünschte Verteilung ohne das Fehleranfällig selber machen zu müssen.



  • 1. Ich dachte das meinte er damit o.o deswegen habe ich es so umgeschrieben..

    2. Achso ich habe "Moduloperator" gelesen 😃 Modulooperator kenne ich natürlich, und ja:

    int i;
      time_t t;
      time(&t);
      srand((unsigned int)t);
    

    und

    rand() % 10
    

    Habe ich aus dem Internet kopiert da es in meinem jetzigen C++-Buchaufgetaucht aber nochnicht erklärt wurde, ich aber trozdem schon mit Zeit und Zufallszahlen programmieren wollte. (Deswegen habe ich den Teil an Quellcode kopiert.)



  • Mit jedem rand() wird eine neue Zufallszahl generiert.
    Also hast du bei jedem if eine neue Zahl bekommen.



  • DirkB schrieb:

    Was soll das else Zaehler--; ? Welcher Fall soll da denn eintreten?

    das

    else Zaehler--;
    

    ist dafür da weil komischerweise manchmal der Zähler höher geht ohne das eine Zahl zwischen 1-10 ausgewählt wurde, das ist auch etwas das mich verblüfft.. weil ich eigentlich nur Zufallszahlen zwischen 1-10 dem Operator zugewiesen habe...


  • Mod

    Moorky Dragonstrike schrieb:

    DirkB schrieb:

    Was soll das else Zaehler--; ? Welcher Fall soll da denn eintreten?

    das

    else Zaehler--;
    

    ist dafür da weil komischerweise manchmal der Zähler höher geht ohne das eine Zahl zwischen 1-10 ausgewählt wurde, das ist auch etwas das mich verblüfft.. weil ich eigentlich nur Zufallszahlen zwischen 1-10 dem Operator zugewiesen habe...

    Du hast 0-9, nicht 1-10. Hast du dir meinen Code oben mal angeguckt?



  • Moorky Dragonstrike schrieb:

    ist dafür da weil komischerweise manchmal der Zähler höher geht ohne das eine Zahl zwischen 1-10 ausgewählt wurde, das ist auch etwas das mich verblüfft.. weil ich eigentlich nur Zufallszahlen zwischen 1-10 dem Operator zugewiesen habe...

    Das kam wegen dem:

    DirkB schrieb:

    Mit jedem rand() wird eine neue Zufallszahl generiert.
    Also hast du bei jedem if eine neue Zahl bekommen.

    Da kann es durchaus mal passieren, dass keine Zahl passte.



  • SeppJ schrieb:

    @asdfasdf: Übertreib mal nicht. Schätz mal ab, wie viele Versuche du machen musst, um festzustellen, dass das nicht gleichverteilt ist. Das ist gleichverteilt genug für praktisch jeden Zweck. Erst wenn die Zahl unterschiedlicher Zahlen ein signifikanter Teil von RAND_MAX wird (und keine Zweierpotenz ist), sollte man sich so langsam Sorgen machen. Bei 10 ist das sicher nicht relevant. Auch nicht bei 100 oder 1000. (Bei 10000 allerdings schon, wenn RAND_MAX nur 2 hoch 15 sein sollte)

    Ich dachte er meint das Problem mit den niederwertigen Bits von LCGs -- weswegen man bei "Zufallszahlen unbekannter Güte" nicht Modulo verwenden sollte um die Zahlen in eine Range zu pressen.



  • SeppJ schrieb:

    Moorky Dragonstrike schrieb:

    DirkB schrieb:

    Was soll das else Zaehler--; ? Welcher Fall soll da denn eintreten?

    das

    else Zaehler--;
    

    ist dafür da weil komischerweise manchmal der Zähler höher geht ohne das eine Zahl zwischen 1-10 ausgewählt wurde, das ist auch etwas das mich verblüfft.. weil ich eigentlich nur Zufallszahlen zwischen 1-10 dem Operator zugewiesen habe...

    Du hast 0-9, nicht 1-10. Hast du dir meinen Code oben mal angeguckt?

    Ja den habe ich gesehen und selbst im Programm 1000000000 mal durchlaufen lassen, es funktioniert ziemlich gut, ich bin aber noch dabei zu verstehen wie das Programm funktioniert, des sieht ganz anders aus als ich meist meine Programme schreibe (ich kenn zwar jeden befehl aber die struktur ist anders)
    Liegt vielleicht auch daran das ich im Sachen Quellcodestruktur noch ein Anfänger bin und deswegen auch sowas wie "Der Quellcode ist schrecklich unübersichtlich" kommt 😛



  • Moorky Dragonstrike schrieb:

    DirkB schrieb:

    Was soll das else Zaehler--; ? Welcher Fall soll da denn eintreten?

    das

    else Zaehler--;
    

    ist dafür da weil komischerweise manchmal der Zähler höher geht ohne das eine Zahl zwischen 1-10 ausgewählt wurde, das ist auch etwas das mich verblüfft.. weil ich eigentlich nur Zufallszahlen zwischen 1-10 dem Operator zugewiesen habe...

    Ohje, bitte Hirn einschalten.
    Wenn du 10000 Runden machst...
    Und in jeder Runde 6 mal würfelst...
    Beim 1. Wurf pro Runde guckst du nur ob du ne eins gewürfelt hast,
    beim 2. Wurf pro Runde guckst du nur ob du ne zwei gewürfelt hast,
    beim 3. Wurf pro Runde guckst du nur ob du ne drei gewürfelt hast,
    usw.

    Würde es dich dann wundern wenn die Summe "Anzahl-Einsen + Anzahl-Zweien + Anzahl-Dreien..." zum Schluss nicht der Runden-Anzahl entspricht?

    Du sollst nur ein mal pro Runde würfeln, ist das so schwer zu verstehen?



  • hustbaer schrieb:

    Moorky Dragonstrike schrieb:

    DirkB schrieb:

    Was soll das else Zaehler--; ? Welcher Fall soll da denn eintreten?

    das

    else Zaehler--;
    

    ist dafür da weil komischerweise manchmal der Zähler höher geht ohne das eine Zahl zwischen 1-10 ausgewählt wurde, das ist auch etwas das mich verblüfft.. weil ich eigentlich nur Zufallszahlen zwischen 1-10 dem Operator zugewiesen habe...

    Ohje, bitte Hirn einschalten.
    Wenn du 10000 Runden machst...
    Und in jeder Runde 6 mal würfelst...
    Beim 1. Wurf pro Runde guckst du nur ob du ne eins gewürfelt hast,
    beim 2. Wurf pro Runde guckst du nur ob du ne zwei gewürfelt hast,
    beim 3. Wurf pro Runde guckst du nur ob du ne drei gewürfelt hast,
    usw.

    Würde es dich dann wundern wenn die Summe "Anzahl-Einsen + Anzahl-Zweien + Anzahl-Dreien..." zum Schluss nicht der Runden-Anzahl entspricht?

    Du sollst nur ein mal pro Runde würfeln, ist das so schwer zu verstehen?

    Tut mir leid o.o das ist das erste mal das ich diese Operator (rand) verwende deswegen wusste ich nicht das er dann 10 mal in einer Runde eine andere Zahl nimmt.. habe mich da vertahen.


  • Mod

    Moorky Dragonstrike schrieb:

    Liegt vielleicht auch daran das ich im Sachen Quellcodestruktur noch ein Anfänger bin und deswegen auch sowas wie "Der Quellcode ist schrecklich unübersichtlich" kommt 😛

    Ja, das kann ich mir vorstellen. Aber wirklich anders schreiben kann ich das nicht, bloß noch abstrakter. Das ist schon die einfachste Stufe, die noch geht, ohne weh zu tun. Wenn du Fragen dazu hast, dann stell sie. Für alle nochmal der Code ohne Link zu ideone:

    #include <ctime>
      #include <iostream>
      #include <cstdlib>
    
      using namespace std;
    
      int main()
      {
        srand(time(0));
    
        const unsigned max = 10000;
        unsigned counter[10] = {0};
        for(unsigned i = 0; i < max; ++i)
        {
          ++counter[rand() % 10];
        }
        cout << "Zufallszahlen Wahrscheinlichkeitsberechner (von 1-10):\n\n";
        cout << "Zaehler: " << max << "\n\n";
        for (unsigned i = 0; i < 10; ++i)
          cout << "Zahl " << i + 1 << ": " << counter[i] << " = " << 1.*counter[i]/max*100 << "%\n";
      }
    


  • Moorky Dragonstrike schrieb:

    Tut mir leid o.o das ist das erste mal das ich diese Operator (rand) verwende deswegen wusste ich nicht das er dann 10 mal in einer Runde eine andere Zahl nimmt.. habe mich da vertahen.

    Klar kommen da immer andere Zahlen raus.

    Erklär mir mal wie du dir das vorgestellt hast - also woher rand() wissen soll wann du eine neue Zahl möchtest.

    Wobei... ich weiss eh dass du darüber nicht nachgedacht hast. Daher auch das "Hirn einschalten!". 😉


Anmelden zum Antworten