boost random
-
Was bewirkt 42u in generator(42u) genau?
#include <conio.h> #include <iostream> #include <boost/random/linear_congruential.hpp> #include <boost/random/uniform_real.hpp> #include <boost/random/variate_generator.hpp> using namespace std; int main() { int n; double start, ende, zufallszahl, m = 0.0; cout << "Anzahl: "; cin >> n; cout << "Startzahl: "; cin >> start; cout << "Endzahl: "; cin >> ende; boost::minstd_rand generator(42u); generator.seed( unsigned (time(0)) ); boost::uniform_real<> uni_dist(start,ende); boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > uni(generator, uni_dist); cout.setf(ios::fixed); cout << n << " samples of a uniform distribution in [" << start <<".."<< ende << "]:\n\n"; for(int i = 0; i < n; ++i) { zufallszahl = uni(); cout << zufallszahl << '\t'; m += zufallszahl; } m /= n; cout << "\n\nMittelwert: " << m << endl; getch(); }
-
42 - wahrscheinlich eine beliebige Zahl. 42 weil sie so cool ist.
u - unsigned
-
is 42 nicht die Antwort auf die Frage nach dem Leben, dem Universum usw. ?
-
Danke für die interessanten Antworten.
Mal was anderes. Man will den Generator ja nicht mitten im Anwendungsprogramm haben. Kann man das wie folgt durch Abtrennung über einen namespace lösen, oder ist das nicht o.k.?
#include <conio.h> #include <iostream> #include <boost/random/linear_congruential.hpp> #include <boost/random/uniform_real.hpp> #include <boost/random/variate_generator.hpp> using namespace std; namespace zufall { boost::minstd_rand generator(42u); void starten() { generator.seed( unsigned (time(0)) ); } double zahl(double start, double ende) { boost::uniform_real<> uni_dist(start,ende); boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > uni(generator, uni_dist); return uni(); } } int main() { zufall::starten(); int n; cout << "Anzahl: "; cin >> n; double zufallszahl, m = 0.0; cout.setf(ios::fixed); cout << n << " samples of a uniform distribution.\n\n"; for(int i = 0; i < n; ++i) { zufallszahl = zufall::zahl(0, 1000); //cout << zufallszahl << '\t'; m += zufallszahl; } m /= n; cout << "\n\nMittelwert: " << m << endl; getch(); }
-
Erhard Henkes schrieb:
ist das nicht o.k.?
nee, ist nicht ok.
namespace zufall
englisch bleiben bei so elementaren tools. auf deutsch kannste in höheren schichten gerne wechseln und ich empfehle das sogar. aber her unten bleib mal beim üblichen.
boost::minstd_rand generator(42u);
ne globale variable? ok, sehe den sinn. und nen singleton hier zu bemühen, ist nicht ideal.
void starten() { generator.seed( unsigned (time(0)) ); }
muß hier etwa einer immer starten vorher aufrufen? ach, das hätte doch auch ein konstruktor selber machen können. (übrigens sehe ich keinen sinn im cast nach unsigned.)
oder gleich mal
boost::minstd_rand generator(time(0));
dann könnten die nubes nicht immer vergessen, srand() aufzurufen oder es in innere schleifen reinhauen. paßt zwar nicht zum rest von c++, hier zu bezahlen, auch wenn man es nicht braucht, ist aber nicht so schrecklich teuer.
double zahl(double start, double ende) { boost::uniform_real<> uni_dist(start,ende); boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > uni(generator, uni_dist); return uni(); }
bestimmt berwirkt dieser code irgendwas. aber irgendwie konnte die bedeutung sehr gut versteckt werden.
ich schätze mal, du wolltest ne klasse anbieten, die im ctor start() aufruft und zahl() als methode hat. dann fliegt auch der namespace weg. hast ja deine schnuckelige klasse. oder schreibt mann dann ne klasse in nen namespace gleichen namens? (nein, das war kein vorschlag.)
statt zahl() muß natürlich wirklich ein besserer name her. leider ein englicher, aber wenn man mit rand(), srand(), time(), random(), ranomize() und lauter englichen bezeichnern aus boost arbeitet, wäre es verwirrend, sich tools zu bauen, die das gleiche machen oder vielleicht mal ein double-paar statt eines int-paares nehmen und nur deshalb gleich deutsche namen haben.
-
#include <conio.h> #include <iostream> #include <boost/random/linear_congruential.hpp> #include <boost/random/uniform_real.hpp> #include <boost/random/variate_generator.hpp> using namespace std; namespace boostRandom { boost::minstd_rand generator( time(0) ); double generateNumber(double start, double end) { boost::uniform_real<> uni_dist(start,end); boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > uni(generator, uni_dist); return uni(); } } int main() { int n; cout << "Anzahl: "; cin >> n; double zufallszahl, m = 0.0; cout.setf(ios::fixed); cout << n << " samples of a uniform distribution.\n\n"; for(int i = 0; i < n; ++i) { zufallszahl = boostRandom::generateNumber(0, 1000); //cout << zufallszahl << '\t'; m += zufallszahl; } m /= n; cout << "\n\nMittelwert: " << m << endl; m = 0.0; for(int i = 0; i < n; ++i) { zufallszahl = boostRandom::generateNumber(1000, 2000); //cout << zufallszahl << '\t'; m += zufallszahl; } m /= n; cout << "\n\nMittelwert: " << m << endl; getch(); }
Hallo Volkard,
danke für deine Tipps. Nur die naheliegende Idee der Klasse leuchtet mir noch nicht vollends ein. Warum sollte man in main() ein lokales Objekt erzeugen (man könnte es alternativ global direkt hinter der Klasse erzeugen: class boostRandom{}generator;)? Ob ich nun boostRandom::generateNumber(a, b); oder generator.generateNumber(a, b); schreibe, ist doch für den Anwender ziemlich unwichtig.Hier die Lösung mit der Klasse zum Vergleich:
#include <conio.h> #include <iostream> #include <boost/random/linear_congruential.hpp> #include <boost/random/uniform_real.hpp> #include <boost/random/variate_generator.hpp> using namespace std; class boostRandom { public: boostRandom() { boost::minstd_rand generator( time(0) ); } double generateNumber(double start, double end) { boost::uniform_real<> uni_dist(start,end); boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > uni(generator, uni_dist); return uni(); } private: boost::minstd_rand generator; }; int main() { boostRandom generator; // Zufallsgenerator int n; cout << "Anzahl: "; cin >> n; double zufallszahl, m = 0.0; cout.setf(ios::fixed); cout << n << " samples of a uniform distribution.\n\n"; for(int i = 0; i < n; ++i) { zufallszahl = generator.generateNumber(0, 1000); //cout << zufallszahl << '\t'; m += zufallszahl; } m /= n; cout << "\n\nMittelwert: " << m << endl; m = 0.0; for(int i = 0; i < n; ++i) { zufallszahl = generator.generateNumber(1000, 2000); //cout << zufallszahl << '\t'; m += zufallszahl; } m /= n; cout << "\n\nMittelwert: " << m << endl; getch(); }
-
Erhard Henkes schrieb:
Nur die naheliegende Idee der Klasse leuchtet mir noch nicht vollends ein. Warum sollte man in main() ein lokales Objekt erzeugen (man könnte es alternativ global direkt hinter der Klasse erzeugen: class boostRandom{}generator;)? Ob ich nun boostRandom::generateNumber(a, b); oder generator.generateNumber(a, b); schreibe, ist doch für den Anwender ziemlich unwichtig.
aber das objekt der eigenen klasse hätte ich global gemacht.
ich mag nicht mit "irgendwelchen" globalen variablen leben, die vor mir versteckt sind, deren wirkung mir schleierhaft ist. mit funktionen, die seiteneffekte haben.
gegen ein globales objekt ist wenig zu sagen. und wer objekt.rand() aufruft, ändert genau das.
ist die zufallszahlenklasse eigentlich threadfest? nicht? dann hau ich mir einfach in jeden thread so ein objekt. solche freiheiten und solche klarheit, wie man probleme umgeht, verschwinden bei deimen versteckspiel mit der funktion und dem geheimen globalen objekt.