Lottozahlen mach ich was falsch?



  • Hallo,

    stimmt hier etwas mit dem Zufall nicht?
    Es sind immer dieselben Zahlen, wie kann das sein? Sogar bei neuem CMD Fenster.
    C:\ConsoleApplication3.exe
    41test17test34test0test19test24test

    C:\ConsoleApplication3.exe
    41test17test34test0test19test24test

    #include <iostream>
    #include <cstdlib>
    
    int main()
    {
    	int lotto[6];
    	lotto[0]= rand() % 50;
    	lotto[1] = rand() % 50;
    	lotto[2] = rand() % 50;
    	lotto[3] = rand() % 50;
    	lotto[4] = rand() % 50;
    	lotto[5] = rand() % 50;
    
    	int i;
    	for  (i = 0; i < 6;i++)
    	std::cout << lotto[i] << "test";
    }
    


  • Du initialisierst den Zufallsgenerator nicht (mit srand).
    Dann wird es zufälliger, allerdings verhinderst du dadurch noch nicht, dass Zahlen doppelt gezogen werden.



  • C++11 hat einen komfortablen random generator eingebaut: https://www.c-plusplus.net/forum/333884



  • Erhard Henkes schrieb:

    komfortablen

    lol, der PRNG von C++11 ist alles, aber nicht komfortabel.



  • komfortable schrieb:

    lol, der PRNG von C++11 ist alles, aber nicht komfortabel.

    Dafür aber Richtig. Die Variante mit Modulo x den Zahlenbereich hinzubiegen funktioniert auch nur wenn RAND_MAX ein Vielfaches von x ist. Ansonsten kommen kleinere Zahlen etwas häufiger vor.



  • sebi707 schrieb:

    komfortable schrieb:

    lol, der PRNG von C++11 ist alles, aber nicht komfortabel.

    Dafür aber Richtig.

    Sagen wir besser. Die kleine Abweichung spielt hier keine Rolle, daher würde ich bei Anfängern weiterhin zu rand und srand(time(nullptr)) raten.



  • Ist auf jeden Fall einfacher, als selbst einen korrekten Generator zu bauen. Du kannst aber gerne meinen alten Generator verwenden oder auf aktuellen Stand bringen: http://codepad.org/ceu5N7pU



  • ich habe ein wenig gegoogelt und es nun *fast* geschafft.
    Mein Problem ist, wie sage ich ihm was minumum und maximum sein soll? auf mein rd.min() %1 hört er nicht...

    #include <iostream>
    #include <random>
    
    int main()
    {
    	int lotto;
    
    	int i=0;
    	for (i = 1; i < 7; i++)
    	{
    		std::random_device rd;
    		rd.min() %1;
    		rd.max() %50;
    		int dice_roll= rd();
    		std::cout << "Lottozahl " << i << ": " << dice_roll << std::endl;
    	}
    }
    


  • Notlösung aber zumindest schnell:

    #include <iostream>
    #include <random>
    
    int main()
    {
    	int i;
    	for (i = 1; i < 7; )
    	{
    		std::random_device rd;
    		int number = rd();
    
    			while (number >= 50) {
    				number = rd() / 8689;
    			}
    			if (number <= 50 && number >= 1)
    			{
    			std::cout << "Lottozahl " << i << ": " << number << std::endl;
    			i = i++;
    		}
    		else {
    			i = i;
    		}
    	}
    }
    


  • Zuf11 schrieb:

    Notlösung

    Warum glaubst Du eine Notlösung zu brauchen?

    Zuf11 schrieb:

    aber zumindest schnell:

    Nein.

    Das ist ziemlicher Mist, den Du da aus dem Internet zusammengeklaubt und dann angepasst hast. Schnell wieder vergessen.

    Da gefällt mir die erste Lösung noch besser.
    Bau vielleicht noch eine Schleife ein, die das Array befüllt und dann lager das Befüllen in eine Funktion aus.

    Was ist eigentlich mit doppelt gezogenen Zahlen?

    PS: Stell die Warnungen Deines Compilers ein!



  • Zuf11 schrieb:

    ich habe ein wenig gegoogelt und es nun *fast* geschafft.
    Mein Problem ist, wie sage ich ihm was minumum und maximum sein soll? auf mein rd.min() %1 hört er nicht...

    Nicht raten! Programmieren ist nicht Raten, du musst genau wissen, was du tust.

    std::random_device::min()/max() liefern den minimalen Wert zurück, den std::random_device::operator()() berechnen kann.

    Die random Bibliothek unterscheidet zwei Konzepte: Generatoren und Verteilungen. Generatoren wie std::random_device liefern einfach nur zufällige Zahlen. Die Verteilungen mappen diese Zahlen dann auf ein entsprechendes Intervall.

    Du willst in deinem Fall Ganzzahlen, also nimmst du die Verteilung std::uniform_int_distribution<int>. Diese Ganzzahlen sollen im Intervall [1, 49] liegen, diese beiden Zahlen übergibst du dem Konstruktor. Anschließend rufst du den operator() der Verteilung auf und übergibst ihm irgendeinen Generator.

    Mehr Details gibts hier: http://en.cppreference.com/w/cpp/numeric/random



  • C++11 bietet einen komfortablen Zufallsgenerator. Versuch mal dieses kleine Programm. Wegen set gibt es keine Zahl doppelt.

    #include <ctime>
    #include <iostream>
    #include <random>
    #include <set>
    
    int main() {
      std::minstd_rand rd(std::time(0));
      std::set<unsigned int> lottozahlen;
      while(lottozahlen.size() < 6) 
        lottozahlen.insert(1+rd()%49);
      for(auto wert : lottozahlen) 
        std::cout << wert << ' ';
      std::cout << '\n';
    }
    


  • wofür ist das Modulo 49 ??



  • heavylotto schrieb:

    C++11 bietet einen komfortablen Zufallsgenerator. Versuch mal dieses kleine Programm. Wegen set gibt es keine Zahl doppelt.

    Das ist kein bisschen besser als rand().



  • mod_? schrieb:

    wofür ist das Modulo 49 ??

    damit nur Zahlen von 0 bis 48 erzeugt werden. +1 macht dann einen Bereich von 1 bis 49.



  • Wenn dann bitte so:

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(1, 49);
    
    std::set<int> lottozahlen;
    while(lottozahlen.size() < 6)
      lottozahlen.insert(dist(gen));
    

    Ist zwar etwas umständlich, aber so gibts vernünftig verteilte Zufallszahlen.



  • komfortable schrieb:

    sebi707 schrieb:

    komfortable schrieb:

    lol, der PRNG von C++11 ist alles, aber nicht komfortabel.

    Dafür aber Richtig.

    Sagen wir besser. Die kleine Abweichung spielt hier keine Rolle, daher würde ich bei Anfängern weiterhin zu rand und srand(time(nullptr)) raten.

    Warum etwas empfehlen, was von C++ 11 als deprecated eingestuft und ab c++17 vermutlich nicht mehr teil von C++ sein wird?
    Abgesehen davon, ist bei MS der Wertebereich auf 32767 beschränkt, siehe https://msdn.microsoft.com/en-us/library/2dfe3bzd.aspx.



  • sebi707 schrieb:

    Wenn dann bitte so:

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(1, 49);
    
    std::set<int> lottozahlen;
    while(lottozahlen.size() < 6)
      lottozahlen.insert(dist(gen));
    

    Ist zwar etwas umständlich, aber so gibts vernünftig verteilte Zufallszahlen.

    Ja. Ist umständlich. Aber wieso das besser verteilte Zufallszahlen als

    minstd_rand
    

    , das

    std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647>
    

    entspricht, geben soll, musst du erstmal zeigen. Nur behaupten reicht nicht.



  • LCGs gibts schon ewig und ist quasi der einfachste Zufallszahlengenerator den man so bauen kann. Ein tolles "Feature" ist z.B. das sich Ebenen ergeben wenn man die Zufallszahlen entsprechend aufträgt (https://en.wikipedia.org/wiki/Linear_congruential_generator). Aber allein wegen dem Modulo disqualifiziert sich deine Lösung. Man rechne mal die Anzahl der Möglichen Werte von minstd_rand (2147483647) Modulo 49 und erhält 43. Damit kommen in deiner Lösung die Zahlen <=43 leicht häufiger vor als die Zahlen >43.


  • Mod

    sebi707 schrieb:

    Damit kommen in deiner Lösung die Zahlen <=43 leicht häufiger vor als die Zahlen >43.

    Und zwar 0.000002% häufiger. Absolut unbrauchbar.


Anmelden zum Antworten