random
-
Hallo zusammen,
ich möchte gerne 1000 Zahlen generieren zwischen 0-99 und dies lasse ich 100 mal wiederholen:
#include <time.h> int main (int argc, char* argv[]) { for(int i = 0 ; i < 100 ; i++) { srand(clock()+ time(NULL)); for(int j = 0 ; j < 1000 ; j++) { std::cout << rand()%100 << " - " ; } std::cout << std::endl << std::endl; } return 0; }Folgendes Problem erhalte ich nun:
- erst ca. jede 10 Wiederholung wechseln die generierten Zahlen.Mit was kann ich srand initialisieren, so das ich bei jeder Wiederholun neue Zufallszahlen erhalte.
mfg
flownfluid
-
Mit was ist völlig egal, aber vielleicht solltest Du nur einmal initialisieren.
Bekanntlich läuft die Zeit nur in begrenzten Intervallen weiter

-
LordJaxom schrieb:
Bekanntlich läuft die Zeit nur in begrenzten Intervallen weiter

Darüber kann man sich streiten. Du redest von der Auflösung von time()!
-
Man sollte
man rand schrieb:
In Numerical Recipes in C: The Art of Scientific Computing (William H. Press, Brian P. Flannery, Saul A. Teukolsky, William T. Vetterling; New York: Cambridge University Press, 1992 (2nd ed., p. 277)), the following comments are made:
"If you want to generate a random integer between 1 and 10, you should always do it by using high-order bits, as in
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
and never by anything resembling
j = 1 + (rand() % 10);
(which uses lower-order bits)."
bedenken...
Greetz, Swordfish
-
Es ist mir auch klar das die time(NULL) nur im sekundentakt wechselt. Ich muss schlussendlich im Code das srand immer wieder von neuem initialisieren und so müsste es doch irgendwie einen Wert geben der sich ständig verändert.
Ideal wäre es eben wenn man mit den Anzahl clock ticks arbeiten könnte. clock() gibt ja diese auch zurück aber leider nur in 1'000 Schritten und das ist mir leider zuwenig.
Das ich srand nicht nur einmal initialisieren kann liegt daran das ich eine Langzeitstudie machen muss und somit 1000 * 1000 Objekte kreieren muss um eine auschlaggebendes Ergebniss zu erhalten.
Also gibt es ein Befehl welcher die wirklichen Anzahl clock ticks zurück gibt?
vielen Dank
-
flownfluid schrieb:
Das ich srand nicht nur einmal initialisieren kann liegt daran das ich eine Langzeitstudie machen muss und somit 1000 * 1000 Objekte kreieren muss um eine auschlaggebendes Ergebniss zu erhalten.
Warum ist das so? Du kannst es doch trotzdem nur 1x initialisieren, und ab da dann jedesmal durch rand() eine (pseudo-)zufaellige Zahl bekommen, ohne sich wiederholende Sequenzen.
greetz JaNnaR
-
Da schlussendlich folgendes gebraucht wird :
for(int i = 0 ; i < 1000 ; i++) { Auto* po_meinAuto = new Auto(); for(int j = 0 ; j < 1000 ; j++) { po_meinAuto->fahrenLos(); } delete po_meinAuto; }In der Klasse Auto wird halt nun immer das srand() neu initialisiert. Da es eine Studie wird, darf ich den Code in der Klasse Auto nicht ändern.
-
Ich glaub' da liegt ein Verständnisproblem vor:
srand( ) initialisiert den Zufallsgenerator. Meistens wird dies mit der Systemzeit gemacht. Basierend auf einem daraus generiertem Startwert liefern dann Aufrufe von rand( ) eine Reihe an Zufallszahlen.
Somit sollte der Zufallsgenerator nur einmal beim Programmstart initialisiert werden.
Greetz, Swordfish
-
flownfluid schrieb:
Hallo zusammen,
...
#include <time.h> int main (int argc, char* argv[]) { for(int i = 0 ; i < 100 ; i++) { srand(clock()+ time(NULL)); ... } return 0; }Wie schon geschrieben: Das würde ich sein lassen, weil SoftwareRNDGeneratoren üblicherweise mit "Historie"/"Feedback" arbeiten (also "wissen", wie oft sie aufgerufen werden) und das löscht man mit einer erneuten Initialisierung. Alternativ kannst Du natürlich selbst ein feedback einbauen und rand() in srand() einfließen lassen, aber ob's das wirklich besser macht, bin ich nicht sicher.
Ich habe den Eindruck, Du kannst/willst Dich nicht recht entscheiden, ob Du dem SW-RNDGenerator oder doch lieber "externem Zufall" vertrauen willst. In der Quintessenz bedeutet Deine Programmierung nämlich, dass Du einen anderen RND-Mechanismus haben möchtest als rand() (wobei Du hier clock() und time() nimmst)
.Ich würde rand nehmen und gut ist. Wenn er Dir nicht reicht, solltest Du ganz auf rand verzichten und das letzte "Clockbit" (systemcall; kein C++-Standard) sammeln oder einen anderen (am besten Hardware-)RNDGenerator verwenden.
Gerade bei wissenschaftlichen Arbeiten ist rand manchmal gar kein schlechter Kandidat, weil er zwar viele RND-Kriterien erfüllt (Abdeckung, Unkorrelliertheit, ....) aber doch reproduzierbar ist. Damit kann man die Programmkorrektheit oftmals gut verifizieren und Fehler finden ... und wo man "harten Zufall" braucht, sollte man sowieso einen HW-Generator verwenden.Gruß,
Simon2.
-
Vielleicht drücke ich mich einwenig falsch aus:
- In der normalen Anwendung wird die Klasse Auto nur einmal erzeugt, sprich das srand() wird nur einmal initialisiert. (Somit tritt hier das Problem gar nicht auf)
Nun die Klasse Auto steuert ein Auto nach gewissen Wahrscheinlichkeiten entweder nach links, grade aus, nach rechts etc...
- Nun musste ich schauen ob sich das Auto nach 1'000 mal einer Fortbewegung (Methode fahrenLos()) sich an die Wahrscheinlichkeiten annährt, dies ging auch ohne Problem.
-Nun muss ich das gleiche Spiel mit 1000 Autos wiederholen. Und nun folgt eben mein Problem:
Da ein Zyklus (1'000 mal fahrenLos) unter einer Sekunde liegt wird das darauffolgende neue Auto mit den gleichen Zufallszahlen generiert. Folglich verfälscht dies die Studie.
mögliche Lösungen.
- ich mache immer zwischen den neuen Autos 1sek. Pause
- ich mache die Studie mit doppelt so vielen Fahrzeugen
oder :es gibt eine Möglichkeit srand so zu initialisieren, das man immer eine neue Zahl erhält, ohne irgend ein Wert zu übergeben.
Für mich wäre es die interessanteste Lösung weil so die Testreihen weniger Zeit in anspruch nehmen.
Ich hoffe nun das ich mich einwenig klarer Ausgedrückt habe...
Gruss
-
flownfluid schrieb:
es gibt eine Möglichkeit srand so zu initialisieren, das man immer eine neue Zahl erhält, ohne irgend ein Wert zu übergeben.
Da du nicht an den srand()-Aufruf rankommst, dürfte das etwas schwierig werden. Andernfalls wäre es eine Möglichkeit, die aktuelle Zählernummer in die Initialisierung einzuklinken:
timt_t t0=time(NULL); for(int i=0;i<1000;++i) { srand(t0+i); ... }Aber das scheint bei dir ja nicht möglich zu sein (ohne Auto::Auto() aufzubohren), da bleibt nur noch, die Wartezeit zwischen den Runden zu erhöhen.
(btw hört es sich nach einem Designfehler an, wenn jedes Auto den globalen Zufallsgenerator neu initialisiert)
-
Genau. Da braucht man nicht lange drumherumzureden, die Auto-Klasse ist fehlerhaft (punkt)

Einen Zufallsgenerator initialisiert man ein einziges Mal.
-
flownfluid schrieb:
Vielleicht drücke ich mich einwenig falsch aus:
...
mögliche Lösungen.- ich mache immer zwischen den neuen Autos 1sek. Pause
- ich mache die Studie mit doppelt so vielen Fahrzeugen
...und:
LordJaxom schrieb:
...Einen Zufallsgenerator initialisiert man ein einziges Mal.

Ich nehme Antwort 3.

Gruß,
Simon2.
-
Vielen Dank für eure Antworten...
Werde es halt mit den Pausen realisieren...
So zur Anregung:
Ihr habt ein Programm gekauft welches irgendeine Zahl zurückgibt.
Nun wollt ihr schauen ob es ein zweites Mal die gleiche Zahl zurückgibt, folglich startet ihr das Programm nochmals und es gibt eventuell eine andere Zahl zurück.Fakt ist das das Programm zweimal gestartet wird und zweimal ein random init macht mit einem seed wert.
Nach meiner Meinung nach anderst unmöglich?!?
-
Scheiss doch auf die unnedige rand().
Nimm den Mersenne Twister, damit hast du gar keine Probleme und der ist "etwas " schneller...
http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
-
Sers schrieb:
Scheiss doch auf die unnedige rand().
Nimm den Mersenne Twister, damit hast du gar keine Probleme und der ist "etwas " schneller...
http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.htmldas schreiben die zwar, aber meine messungen haben regelmäßig ergeben, daß std::rand schneller ist.
-
Kann man sowas mit einem high precision timer messen?
-
Sers schrieb:
Kann man sowas mit einem high precision timer messen?
jo.
aber für den mersenne twister brauchste als anzahl eh ein vielfaches der puffergröße oder ganz viele zahlen, um nen guten durchschnitt zu bekommen. sowas kannste auch low precision messen, wenn die messstrecke lang genug ist.