Nochmal Frage zu Zufallszahlen



  • Hallo,

    mir ist noch ein Problem an meinem Programm aufgefallen und hoffe, dass ihr mir weiterhelfen könnt. Und zwar möchte ich bei jedem Programmstart neue Zufallszahlen erstellen, die jedesmal anders sind. Ich mache das also mithilfe eines Saatpunkts, den ich setze. Allerdings kann dieser Saatpunkt nur einmal gesetzt werden und nicht mehrmals. Darin liegt auch schon mein Problem. In einer seperaten Funktion einer anderen Klasse hab ich folgenden Code zum generieren von Zufallszahlen geschrieben:

    double random_double;
    
    int seed = time(0);
    srand(seed);
    
    random_double = ((double)rand())/RAND_MAX;
    random_double = random_double * 10;
    random_double = random_double + 10;
    

    Hier wird mir eine Zufallszahl zwischen 10 und 20 ausgegeben. Allerdings soll der Saatpunkt nur einmal gesetzt werden und anschließend nur noch die Zufallszahlen mithilfe dieses einen Saatpunktes. So nun meine Frage: Wie bekomme ich es also hin, dass ich den Saatpunkt nur einmal setze beim ersten Aufruf der Funktion und nicht nochmal beim zweiten Aufruf. Ich bekomm das einfach nicht hin. Bitte helft mir. Danke.



  • double random_double;
    static bool setit = true;
    if (setit)
    {
       setit = false;
       int seed = time(0);
       srand(seed);
    }
    
    random_double = ((double)rand())/RAND_MAX;
    random_double = random_double * 10;
    random_double = random_double + 10;
    

    Da wir allerdings im C++ Forum sind würde ich empfehlen das in einer Klasse zu machen.



  • Ja diese Lösung hab ich auch schon ausprobiert. Sie kann ja aber gar nicht funktionieren, da "setit" in deinem Fall ja immer true ist. Wenn ich aber die Funktion, in der die Zufallszahlen generiert werden, mehrmals aufrufe beim Programmstart, dann wird srand() ja immernoch mehrmals aufgerufen. Und mein Problem besteht ja weiterhin. Ich will ja srand() nur einmal beim ersten Aufruf der Funktion abarbeiten und anschließend, wenn die Funktion ein weiteres mal aufgerufen wird, dann natürlich nicht mehr, da srand() nur einmal pro Programmablauf aufgerufen werden soll. Hat jemand vielleicht eine andere funktionierende Version? Danke.



  • Der Code oben funktioniert der bool ist static deklariert.



  • Was bewirkt denn dieses "static"? Ohne static funktioniert es aber nicht oder? Und was mach ich, wenn ich zwei Funktionen habe, die verschiedene Zufallszahlen erzeugen und diese auch mehrmals beide aufgerufen werden? Dann will ich ja immernoch nur einmal srand() aufrufen, ansonsten bekomme ich wieder nicht richtige Zuafallszahlen. Also zum Beispiel:

    1.Funktion (liefert Zufallszahlen zwischen 10 und 20):

    double random_double;
    	static bool abfrage = true;
    	if (abfrage)
    	{
    		abfrage = false;	
    		int seed = time(0);
    		srand(seed);
    	}
    	random_double = ((double)rand())/RAND_MAX;
    	random_double = random_double * 10;
    	random_double = random_double + 10;
    

    2.Funktion (liefert Zufallszahlen zwischen 1000 und 2000);

    double random_double;
    	static bool abfrage = true;
    	if (abfrage)
    	{
    		abfrage = false;	
    		int seed = time(0);
    		srand(seed);
    	}
    	random_double = ((double)rand())/RAND_MAX;
    	random_double = random_double * 1000;
    	random_double = random_double + 1000;
    

    Hierbei befinden sich beide Funktionen in unterschiedlichen Klassen. Könnt ihr mir bei dieser Problematik vielleicht auch einen kleinen Tipp geben oder eventuell eine Problemlösung. Danke.



  • Grammi schrieb:

    Was bewirkt denn dieses "static"? Ohne static funktioniert es aber nicht oder?

    Das static bewirkt, dass die Variable nur _einmal_ definiert wird. Von diesem Zeitpunkt ist sie dann bis zum Programmende verfügbar. Statische Variablen (oder besser Bezeichner) kannst du dir im Prinzip wie globale Variablen vorstellen, mit dem Unterschied, dass sie nur in dem jeweiligen Block ansprechbar sind, in welchem sie definiert wurden (bzw. falls die eine Variable mit einer static-Deklaration global eingeführt wird, ist sie nicht Programmglobal sondern modulglobal...)

    /edit:

    ... bekomme ich wieder nicht richtige Zuafallszahlen...

    "Richtige" Zufallszahlen bekommst du auch nicht, wenn du nur einmal srand() aufrufst.
    Btw.: Was macht es denn für dich nicht möglich zweimal srand() aufzurufen?

    Außerdem finde ich die Funktionen designtechnisch nicht so gut getroffen, sprich, ich würde eine Funktion init_srand() machen. Z.B.:

    void init_srand_with_time()
    {
           static bool is_init = false;
           if(!is_init)
           {
                srand(time(0));
                is_init = true;
           }
    }
    

    Diese Funktion ruft dann einmal srand() mit time(0) auf. Danach kannst du ja mit zwei weiteren Funktionen deine Zufallszahlen in verschiedenen Intervallen generieren...

    Caipi





  • Danke erstmal für eure Infos, aber nun hab ich ja immernoch das Problem, was ich oben geschildert hab, wenn ich zwei unterschidliche Funktionen hab, die sich in unterschiedlichen Klassen befinden und auch mehrmals aufgerufen werden sollen. Und dabei nur einmal srand() aufgerufen werden soll. Könnt ihr mir dabei vielleicht auch noch ein bisschen weiterhelfen? Danke.



  • Grammi schrieb:

    Danke erstmal für eure Infos, aber nun hab ich ja immernoch das Problem, was ich oben geschildert hab, wenn ich zwei unterschidliche Funktionen hab, die sich in unterschiedlichen Klassen befinden und auch mehrmals aufgerufen werden sollen. Und dabei nur einmal srand() aufgerufen werden soll. Könnt ihr mir dabei vielleicht auch noch ein bisschen weiterhelfen? Danke.

    Siehe mein Edit. 😉

    Caipi



  • Ja das würde schon funktionieren, aber bekommt man es auch hin, wie ich es geschildert hab? Das müsste ja eigentlich irgendwie klappen oder? Deine Variante klappt zwar, aber hilft mir nicht wirklich weiter. Aber ich zeig euch einfach mal meinen ganzen Code. Vielleicht versteht ihr dann mein Problem. Aber Vorsicht, der ist ziemlich lang.

    Bauteil.h

    #include <iostream>
    #include <string>
    #include <time.h>
    #include <ctime>
    #include <algorithm>
    #include <iomanip>
    
    #ifndef BAUTEIL_H
    #define BAUTEIL_H
    
    using namespace std;
    
    class Bauteil
    {
    protected:
    	string name;
    
    public:
    	Bauteil();
    	Bauteil(string na);
    	~Bauteil();
    	void setName(string na);
    	virtual void Bauteil::print()
    	{
    		cout << name;
    	}
    };
    
    #endif
    

    Bauteil.cpp

    #include "Bauteil.h"
    
    using namespace std;
    
    Bauteil::Bauteil()
    {
    	name = "";
    }
    
    Bauteil::Bauteil(string na)
    {
    }
    
    Bauteil::~Bauteil()
    {
    }
    
    void Bauteil::setName(string na)
    {
    	name = na;
    }
    

    Temperatursensor.h

    #include "./Bauteil.h"
    
    #ifndef TEMPERATURSENSOR_H
    #define TEMPERATURSENSOR_H
    
    using namespace std;
    
    class Temperatursensor : public Bauteil
    {
    private:
    	double temperatur;
    
    public:
    	Temperatursensor();
    	Temperatursensor(string na);
    	~Temperatursensor();
    	double getTemperatur();	
    	void print();
    
    };
    
    #endif
    

    Temperatursensor.cpp

    #include "./Temperatursensor.h"
    
    using namespace std;
    
    Temperatursensor::Temperatursensor()
    {
    }
    
    Temperatursensor::Temperatursensor(string na)
    {
    	setName(na);
    }
    
    Temperatursensor::~Temperatursensor()
    {
    }
    
    double Temperatursensor::getTemperatur()
    {
    	double random_double;
    	static bool abfrage = true; //HIER LIEGT MEIN PROBLEM
    	if (abfrage)
    	{
    		abfrage = false;	
    		int seed = time(0);
    		srand(seed);
    	}
    	random_double = ((double)rand())/RAND_MAX;
    	random_double = random_double * 10;
    	random_double = random_double + 10;
    	return random_double;
    }
    
    void Temperatursensor::print()
    {
    	cout << setw(8) << name;
    	cout.precision(6);
    	cout << setw(10) << getTemperatur();
    	cout << " Grad Celsius" << endl;
    }
    

    Drucksensor.h

    #include "./Bauteil.h"
    
    #ifndef DRUCKSENSOR_H
    #define DRUCKSENSOR_H
    
    using namespace std;
    
    class Drucksensor : public Bauteil
    {
    private:
    	double druck;
    
    public:
    	Drucksensor();
    	Drucksensor(string na);
    	~Drucksensor();
    	double getDruck();	
    	void print();
    };
    
    #endif
    

    Drucksensor.cpp

    #include "./Drucksensor.h"
    
    using namespace std;
    
    Drucksensor::Drucksensor()
    {
    }
    
    Drucksensor::Drucksensor(string na)
    {
    	setName(na);
    }
    
    Drucksensor::~Drucksensor()
    {
    }
    
    double Drucksensor::getDruck()
    {
    	double random_double;
    	static bool abfrage = true; //HIER LIEGT MEIN PROBLEM
    	if (abfrage)
    	{
    		abfrage = false;
    		int seed = time(0);
    		srand(seed);
    	}
    	random_double = ((double)rand())/RAND_MAX;
    	random_double = random_double * 100;
    	random_double = random_double + 100;
    	return random_double;
    }
    
    void Drucksensor::print()
    {
    	cout << setw(8) << name;
    	cout.precision(7);
    	cout << setw(10) << getDruck();
    	cout << " hPa" << endl;
    }
    

    Geraete.h

    #include "./Temperatursensor.h"
    #include "./Drucksensor.h"
    #include <vector>
    
    #ifndef GERAET_H
    #define GERAET_H
    
    using namespace std;
    
    class Geraet
    {
    private:
    	vector<Bauteil*> bt;
    
    public:
    	Geraet();
    	~Geraet();
    	void add();
    	void print();
    };
    
    #endif
    

    Geraete.cpp

    #include "./Geraet.h"
    
    using namespace std;
    
    Geraet::Geraet()
    {
    }
    
    Geraet::~Geraet()
    {
    }
    
    void Geraet::add()
    {
    	string ausw;
    	char auswahl;
    	string name;
    	do
    	{
    		cout << "Eingabe Sensor" << endl;
    		cout << "--------------------------------" << endl;
    		cout << "t - Temperatursensor" << endl;
    		cout << "d - Drucksensor" << endl;
    		cout << "x - Abbrechen" << endl << endl;
    		cout << "Auswahl: ";
    		do
    		{
    			cin >> ausw;
    			if (ausw.size() == 1)
    			{
    				auswahl = ausw[0];
    				if (auswahl != 't' && auswahl != 'd' && auswahl != 'x')
    				{
    					cout << "Buchstabe muss dem oben entsprechen: ";
    				}
    			} else
    			{
    				auswahl = 'b';
    				cout << "Bitte nur einzelne Buchstaben eingeben: ";
    			}
    		} while (auswahl != 't' && auswahl != 'd' && auswahl != 'x');
    
    		fflush(stdin);
    		cout << endl << endl;
    
    		switch (auswahl)
    		{
    		case 't':
    			cout << "Bitte ID des Sensors eingeben: ";
    			cin >> name;
    			bt.push_back(new Temperatursensor(name));
    			cout << endl;
    			cout << "Temperatursensor hinzugefuegt!" << endl << endl;
    			system("pause");
    			break;
    		case 'd':
    			cout << "Bitte ID des Sensors eingeben: ";
    			cin >> name;
    			bt.push_back(new Drucksensor(name));
    			cout << endl;
    			cout << "Drucksensor hinzugefuegt!" << endl << endl;
    			system("pause");
    			break;
    		case 'x':
    			break;
    		default:
    			cout << "Fehler";
    			break;
    		}
    		system("cls");
    	} while (auswahl != 'x');
    }
    
    void Geraet::print()
    {
    	if (bt.empty() == true)
    	{
    		cout << "Es gibt noch keine Sensoren!" << endl;
    	}
    	else
    	{
    		cout << "Auflistung der Sensoren" << endl;
    		cout << "-----------------------------------" << endl;
    		for(int zaehler = 0; zaehler < (int)bt.size(); zaehler++)
    		{
    			cout << zaehler << " : ";
    			bt.at(zaehler)->print();
    		}
    	}
    }
    

    Main.cpp

    #include "./Geraet.h"
    
    using namespace std;
    
    int main()
    {
    	string ausw;
    	char auswahl;
    	Geraet g;
    	do
    	{
    		cout << "Geraetemanager:" << endl;
    		cout << "----------------------------------" << endl << endl;
    		cout << "a: Neue Sensoren hinzufuegen" << endl;
    		cout << "d: Sensordaten ausgeben" << endl;
    		cout << "x: Programm beenden" << endl << endl;
    		cout << "Auswahl: ";
    		do
    		{
    			cin >> ausw;
    			if (ausw.size() == 1)
    			{
    				auswahl = ausw[0];
    				if (auswahl != 'a' && auswahl != 'd' && auswahl != 'x')
    				{
    					cout << "Buchstabe muss dem oben entsprechen: ";
    				}
    			} else
    			{
    				auswahl = 'b';
    				cout << "Bitte nur einzelne Buchstaben eingeben: ";
    			}
    		} while (auswahl != 'a' && auswahl != 'd' && auswahl != 'x');
    
    		fflush(stdin);
    
    		switch(auswahl)
    		{
    		case 'a':
    			system("cls");
    			g.add();
    			break;
    		case 'd':
    			cout << endl << endl;
    			g.print();
    			cout << endl;
    			system("pause");
    			break;
    		case 'x':
    			break;
    		default:
    			cout << "Fehler!";
    			break;
    		}
    		system("cls");
    	} while (auswahl != 'x');
    	return 0;
    }
    

    Vielleicht fällt euch ja eine Möglichkeit ein, das Problem zu lösen. Wär echt toll. Danke.



  • Hallo,
    Schreibe z.B. statt:

    double Temperatursensor::getTemperatur()
    {
        double random_double;
        static bool abfrage = true; //HIER LIEGT MEIN PROBLEM
        if (abfrage)
        {
            abfrage = false;   
            int seed = time(0);
            srand(seed);
        }
        random_double = ((double)rand())/RAND_MAX;
        random_double = random_double * 10;
        random_double = random_double + 10;
        return random_double;
    }
    

    lieber

    double Temperatursensor::getTemperatur()
    {
        init_srand_with_time(); // Die bereits gepostete Funktion
        double random_double = ((double)rand())/RAND_MAX;
        random_double = random_double * 10;
        random_double = random_double + 10;
        return random_double;
    }
    

    (In der Methode getDruck() ist es eine äquivalente Änderung ;))

    Hier wird auch wenn du einmal die Methode getDruck und einmal die Methode getTemperatur aufrufst nur _einmal_ srand() mit time(0) initalisiert (Aufgrund der static-Variable).

    Caipi



  • Danke für die Hilfe. Manchmal ist die Lösung so einfach, wie in diesem Fall, dass man den Wald vor lauter Bäumen nicht sieht. Nochmals danke für die Denkstütze. Es klappt jetzt alles bestens.


Anmelden zum Antworten