Zufallszahlen zwischen 0 und 1



  • Hallo,

    ich entweickle gerade einen Algorithmus, der Zufallszahlen erstellen soll. Zur Überprüfung habe ich eine Schleife mit Mittelwertberechnung einprogrammiert.

    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    
    using namespace std;
    
    int main()
    {
    	double zufall1, zufall2, zwischen0und1, mittelwert = 0;
    	int eingabe, loop = 0;
    
    	while(eingabe != 0)
    	{
    
    	cin >> eingabe;
    
    	srand( (unsigned)time( NULL ) );
    
    	zufall1 = rand();
    	zufall2 = rand();
    
    		if(zufall1 > zufall2)
    		{
    			zwischen0und1 = zufall2 / zufall1;
    		}
    
    		if(zufall1 < zufall2)
    		{
    			zwischen0und1 = zufall1 / zufall2;
    		}
    
    	cout << zwischen0und1 <<endl;
    	cout << endl;
    
    	++loop;
    
    	mittelwert += zwischen0und1;
    
    	cout << mittelwert/loop << endl;
    	cout << endl;
    
    	}
    
    	return 0;
    }
    

    Allerdings treten 2 Probleme auf:

    1. Der Durchschnitt ist immer ungefähr 0,4, auch bei sehr vielen Durchgängen. Das müsste doch dann eigentlich näher an 0,5 liegen, oder?

    2. Der Zufallswert ändert sich nur jede Sekunde, weil ihm ja die Anzahl der Sekunden seit dem 1.1.1970 zugrunde liegt. Aber wenn ich zum Beispiel mit einer for-Schleife arbeite und schnell viele Zufallszahlen brauche ist das zu langsam. Geht das noch häufiger?

    Vielen Dank für's mitdrübernachdenken 🤡

    Reimer



  • Der Zufallswert ändert sich nicht jede Sekunde?
    Jedes Mal, wenn du rand() aufrufst, bekommst du einen neuen ausgespuckt?

    Die Zahlen sind auch nicht wirklich zufällig. Würdest du srand() jedes Mal mit der gleichen Zahl als Parameter aufrufen, würden immer die gleichen "Zufallswerte" rauskommen. Darum ist die Variante mit der Zeit ganz gut.



  • srand() muss raus aus der schleife. Dann sollte die verteilung viel besser sein.
    Kurt



  • Hier zwei von meinen headern guck mal ob du da was findest

    //zufall.h
    //zum Erstellen einer Zufallszahl
    //Mario Sandler 2005
    
    //Wenn zufall nicht gesetzt ist, d.h header zufall.h noch nicht eingebunden
    #ifndef inc_zufall
    
    //Dann setzte Zufall
    #define inc_zufall
    
    //Header
    #include <ctime>                              //für time() und time_t
    #include <cstdlib>                            //für srand() und rand()
    
    //Wenn delay noch nicht gesetzt ist, etwa vom Programmierer
    #ifndef delay
    //Dann setze delay für die Zeitverzögerung
    #define delay 1
    //von ifndef delay
    #endif
    
    //Namespace
    namespace storm {                             //eigener Namespace
    //#######################################################################################################//
      //Template zufall()
      template <class T> T zufall(T min, T max) { //empfohlen für T = short, int, long
    
        //Deklaration
        T z_zahl;                                 //Die Zufallszahl z_zahl
        time_t start, finish;                     //start und finish der Zeitmessung
    
        //Anfangszeit
        std::time(&start);                             //Zeitmessung beginnt 
    
        //Erste Schleife für Verzögerung
        do {
          std::time(&finish);                          //Zeitmessung endet
        } while(std::difftime(finish, start) < delay); //solange die verstrichene Zeit,
                                                  //nicht so groß ist wie die Verzögerung
                                                  //wird die finish zeitmessung wiederholt.
    
        std::srand((unsigned) std::time(NULL));             //srand wird gesetzt
    
        //Zweite Schleife für die Zufallszahl
        do {
          z_zahl = std::rand();                        //Zufallszahl wird generiert
        } while((z_zahl < min) || (z_zahl > max));//solange die zufallszahl kleiner als das minimum,
                                                  //oder größer als das maximum ist, wird wiederholt
    
        return z_zahl;                            //Rückgabe der Zufallszahl
    
      };                                          //Ende Template zufall()
    
    //#######################################################################################################//
      //Template fastzufall()
      template <class T> T fastzufall(T min, T max) {
    
        //Deklaration
        T z_zahl;
    
        std::srand((unsigned) std::time(NULL));             //srand wird gesetzt
    
        //Fastzufallzahlermittlung
        z_zahl = (std::rand())%(max-min+1)+min;        //Zufallszahl wird generiert
                                                  //und mithilfe des modulo-Operators %
                                                  //im den richtigen Bereich gesetzt
    
        return z_zahl;                            //Rückgabe der Zufallszahl
    
      };                                          //Ende Template fastzufall()
    
    //########################################################################################################//
      //Funktion boolzufall()
      bool boolzufall() {
    
        //Deklaration
        bool boolwert;
        clock_t zeit;
    
        zeit = std::clock();                              //Zeit wird genommen
    
        if(zeit % 2 == 1)
          return true;
        else
          return false;
    
      }                                           //Ende Funktion boolzufall()
    //########################################################################################################//
    
    }                                             //Ende Namespace
    //für ifndef inc_zufall
    #endif
    
    //zeit.h
    //Zur verzögerung von Ereignisen
    //Thmoas Keck 2005
    
    #ifndef inc_zeit
    #define inc_zeit
    
    #include <ctime>
    using namespace std;
    
    namespace storm {
    
      void sleep(int verz) {
    
        //Deklaration
        time_t start, finish;                     //start und finish der Zeitmessung
    
        //Anfangszeit
        time(&start);                             //Zeitmessung beginnt 
    
        //Schleife für Verzögerung
        do {
          time(&finish);                          //Zeitmessung endet
        } while(difftime(finish, start) < verz); //solange die verstrichene Zeit,
                                                  //nicht so groß ist wie die Verzögerung
                                                  //wird die finish zeitmessung wiederholt.
    
      }                                           //Ende Funktion sleep()
    
      void sleep_short(double verz) {
    
        //Deklaration
        clock_t start, finish;                     //start und finish der Zeitmessung
    
        //Anfangszeit
        start = clock();                             //Zeitmessung beginnt 
    
        //Schleife für Verzögerung
        do {
          finish = clock();                          //Zeitmessung endet
        } while(difftime(finish, start)/1000 < verz); //solange die verstrichene Zeit,
                                                  //nicht so groß ist wie die Verzögerung
                                                  //wird die finish zeitmessung wiederholt.
    
      }                                           //Ende Funktion sleep_short()
    
    }                                             //Ende Namespace
    
    #endif
    

    Spiel einfach mal ein bischen damit rum



  • Erstens solltest du srand() nur einmal am Programmanfang aufrufen (sprich: vor der while-Schleife). Und zweitens ist es etwas Overkill, deinen Zufallswert aus zwei Zahlen zu bestimmen - nimm dafür lieber "zufallswert=(double)rand()/RAND_MAX;"

    @storm: Auch für deinen Quelltext gilt der Hinweis mit dem srand() - einmal am Programmstart reicht völlig 😉



  • CStoll schrieb:

    einmal am Programmstart reicht völlig 😉

    Ich würde das noch krasser ausdrücken. Den Zufallsgenerator mehrfach mit der momentanen Zeit zu initialisieren ist Blödsinn denn dann bekommst du bei mehrfachen Aufruf innerhalb der gleichen Sekunde immer die gleichen Werte.
    Kurt


Anmelden zum Antworten