hallo leute, wie erzeuge ich eine zufallszahl mit random, die sich beim aufruf der random funktion auch ändert? folgender quellcode liefert immer die gleiche zahl: void zufallszahl () { int i; rand ((unsigned) time(NULL)); for(i = 1; i <= 1; i++) { zahl = 0 + ( rand() % 255); printf("erzeugte Zufallszahl %i \n\r" , zahl); return (zahl); } } ich benötige bei jedem aufruf von zufallszahl() allerdings eine andere zahl zwischen 0 und 255.kann mir jemand weiterhelfen?!danke schonmal
moin, ich bin mir nicht mehr ganz sicher, aber müsste beim initialisieren nicht srand() verwendet werden?
Danke erstmal für die schnellen Antworten @Emperor_L0ser (Gast) ja hast recht, hab ich bei mir im Quellcode auch gemacht nur irgendwie beim hierher kopieren gings verloren...;) @CHRiS (Gast) ich will halt nur einen Wert und keine Zahlenfolge....muss eigentlich von 1 bis 2 heißen. Das war allerdings nicht der Fehler. Das Problem ist, dass bei jedem Aufruf der Funktion der gleiche zufallswert erzeugt wird und ich benötige unterschiedliche Werte...weiß nicht wo der fehler liegen soll. Hat noch jemand ne idee?
Hast du srand() in der Funktion aufgerufen? Dann wäre klar, dass da immer das selbe rauskommt.
habe es so implementiert void zufallszahl () { int i; srand ((unsigned) time(NULL)); for(i = 1; i <= 2; i++) { zahl = 0 + ( rand() % 255); printf("erzeugte Zufallszahl %i \n\r" , zahl); return (zahl); } }
> rand ((unsigned) time(NULL));
Eigentlich sollte das einen Fehler vom Compiler bringen, es sei denn, du
hast den zur Funktion gehörenden Header nicht eingebunden. Dann sollte
aber wenigstens eine Warnung kommen. Du meintest vermutlich srand.
geht das?
1 | for(i = 1; i <= 1; i++) |
Gehen tut das schon. Die Schleife wird halt genau einmal ausgeführt.
mhh mal wieder zu langsam ... kommt davon wenn man zwischendurch alles andere macht.
srand() soll natürlich nur einmal ausgeführt werden und nicht bei jedem Aufruf der Funktion erneut. Damit gibst du den Startwert vor, mit dem der Generator initialisiert wird. Wenn du vor jedem Aufruf den Startwert neu setzt, klappt das natürlich nur mäßig gut. >Das Problem ist, dass bei jedem Aufruf der Funktion der gleiche > zufallswert erzeugt wird und ich benötige unterschiedliche Werte Vermutlich nicht bei jedem Aufruf, sondern immer genau eine Sekunde lang bzw bis time() einen neuen Wert liefert.
Um Zahlen von 0 bis 255 (0 und 255 eingeschlossen, was wahrscheinlich deine Absicht ist) zu erzeugen, musst du %256, nicht %255 rechnen. Der Typ von zufallszahl() sollte int sein. > for(i = 1; i <= 2; i++) > ... > return (zahl); > ... Warum zwei Schleifendurchläufe, wenn aus dem ersten sowieso per return herausgesprungen wird? Wieso lässt du die Schleife nicht einfach ganz weg? Vereinfachte Variante:
1 | int zufallszahl() { |
2 | return rand() % 256; |
3 | }
|
4 | |
5 | int main(void) { |
6 | ...
|
7 | srand ((unsigned) time(NULL)); |
8 | ...
|
9 | |
10 | x = zufallszahl(); |
11 | }
|
> Um Zahlen von 0 bis 255 (0 und 255 eingeschlossen, was wahrscheinlich > deine Absicht ist) zu erzeugen, musst du %256, nicht %255 rechnen. Meistens wird eher noch empfohlen, % gar nicht zu verwenden, sondern den Wert passend runterzudividieren bzw -shiften, da manche Zufallszahlengeneratoren bei den unteren Bits nicht so gut mit der Zufallsverteilung sind wie bei den oberen bits. In der Manpage zu rand unter Linux heißt es: ************ The versions of rand() and srand() in the Linux C Library use the same random number generator as random() and srandom(), so the lower-order bits should be as random as the higher-order bits. However, on older rand() implementations, and on current implementations on different systems, the lower-order bits are much less random than the higher-order bits. ************
Es gibt noch ein 2-tes Problem mit der Modulo Version: Die Normalverteilung von rand() kann empfindlich gestört werden. Beispiel: Angenommen der Zufallszahlengenerator liefert Zahlen im Bereich 0 bis 7. Um in den Bereich 0 bis 5 zu kommen wird gemacht: rand() % 6 Um zu sehen, was hier passiert untersuchen wir mal, was bei jeder einzelnen rand() Zahl durch den % 6 entsteht Zahl von rand() % 6 0 0 1 1 2 2 3 3 4 4 5 5 6 0 7 1 Wenn also alle Zahlen die rand() liefert tatsächlich gleich wahrscheinlich sind, dann macht die % 6 Rechnung daraus eine Verteilung in der 0 und 1 doppelt so häufig auftreten wie 2, 3, 4, 5. Sowas wird jeden Kasinobetreiber in den Ruin treiben :-) In C gibt es eine Konstante, aus der man die größte Zahl ablesen kann, die von rand() geliefert werden kann: RAND_MAX Nur dann wenn bei der Berechnung % n das n auch RAND_MAX teilt, bleibt die Normalverteilung erhalten. In allen anderen Fällen wird man sich mit dieser Methode einen Fehler in der Verteilung einhandeln.
> Die Normalverteilung von rand() kann empfindlich gestört werden. Das ist schon richtig, besonders auf 8- und 16-Bit-Systemen, wo der Wertebereich der rand-Funktion nur bis 2**15-1=32767 reicht (bspw. auf dem AVR). Du meinst aber sicher die Gleichverteilung, nicht die Normalverteilung ;-). > Nur dann wenn bei der Berechnung % n das n auch RAND_MAX teilt, Nicht ganz korrekt: Das Gleichverteilung bleibt dann erhalten, wenn n RAND_MAX+1 teilt. Die Zufallszahlen liegen im Bereich 0 bis RAND_MAX, 0 und RAND_MAX eingeschlossen, das sind also RAND_MAX+1 unterschiedliche Werte. Um Zufallszahlen im Bereich 0 bis 255 zu generieren (was der OP vermutlich beabsichtigt) ist also
1 | rand()%256 |
korrekt, wenn - RAND_MAX=256*n-1 und - die rand-Funktion das von Rolf Magnus beschriebene Problem nicht aufweist. Diese Bedingungen sind zumindest für die glibc und die avr-libc erfüllt. Andere Frage in diesem Zusammenhang: Kennt jemand eigentlich eine Methode mit nach oben abschätzbarer Laufzeit, gleichverteilte Zufallszahlen in "krummen" Intervallen (also bspw. 0 bis 5) unter Zuhilfenahme der rand-Funktion zu generieren? Es soll also keine grundlegend neue rand-Funktion entwickelt werden. Mehrfachaufrufe von rand() sind aber erlaubt, wenn die Anzahl der erforderlichen Aufrufe eine obere Grenze hat.
yalu wrote: > Kennt jemand eigentlich eine Methode mit nach oben abschätzbarer > Laufzeit, gleichverteilte Zufallszahlen in "krummen" Intervallen (also > bspw. 0 bis 5) unter Zuhilfenahme der rand-Funktion zu generieren? > > Es soll also keine grundlegend neue rand-Funktion entwickelt werden. > Mehrfachaufrufe von rand() sind aber erlaubt, wenn die Anzahl der > erforderlichen Aufrufe eine obere Grenze hat. Die Methode die ich aus comp.lang.c++ kenne, funktioniert so: Du bestimmst dir das kleinste Vielfache deines n, welches gerade noch unter MAX_RAND liegt. Dann lässt du mit rand() eine Zufallszahl generieren und prüfst, ob sie über dieser Grenze liegt. Wenn ja -> rand() erneut aufrufen und prüfen. Wenn nein, kannst du ganz normal mit dem % weitermachen wie gehabt. Im Grunde verwirfst du einfach alle Zufallszahlen über einer Grenze, wobei die Grenze so gewählt wurde, dass sie ein Vielfaches deines interessierenden Bereiches ist. (Irgendwie bin ich heute nicht in Form. Obige Beschreibung liest sich grauenhaft. Ich hoffe man kann die Idee dahinter rauslesen)
> (Irgendwie bin ich heute nicht in Form. Obige Beschreibung liest > sich grauenhaft. Ich hoffe man kann die Idee dahinter rauslesen) Nee, kein Problem, ich habe das sofort verstanden. So ähnlich mache ich das normalerweise auch, funktioniert ja auch bestens. Der Schönheitsfehler liegt nur darin, dass (wenn auch mit geringer Wahrscheinlichkeit) die rand-Funktion u.U. sehr oft aufgerufen werden muss, bis man einen Wert erhält, der unterhalb der Grenze liegt. Deswegen habe ich oben die Forderung nach abschätzbarer Laufzeit bzw. nach einer oberen Grenze der Anzahl der rand-Aufrufe gegeben. Nur dann ist die Methode bspw. in Anwendungen mit harten Echtzeitanforderungen einsetzbar.
> Du bestimmst dir das kleinste Vielfache deines n, welches > gerade noch unter MAX_RAND liegt. Nicht eher das größte Vielfache?
Das erscheint irgendwie sinnvoller. Aber du hast doch gelesen, dass Karl heinz heute nicht so in Form ist. Und der Leser soll ja auch noch etwas zum mitdenken haben ;-)
kann bitte mal jemand den kompletten Quell code hier rein stellen...danke
kompletten Quellcode wofür? Wenn du einen Generator für saubere Gleichverteilung in jedem beliebigen Bereich (natürlich kleiner RAND_MAX + 1) meinst, dann zb so:
1 | int myRand() |
2 | {
|
3 | int x; |
4 | |
5 | while( (x = rand()) >= RAND_MAX - (RAND_MAX % UpperBound) ) |
6 | ;
|
7 | return x % UpperBound; |
8 | }
|
Wie und warum das funktioniert, sollte aus den Beschreibungen von weiter oben eigentlich klar sein. Wenn deine obere Grenze konstant ist, dann wäre allerdings diese Version besser, da dann der Compiler einen Teil der Berechnungen zur Compilezeit erledigen kann
1 | #define UPPPER_BOUND 10
|
2 | |
3 | int myRand( int UpperBound ) |
4 | {
|
5 | int x; |
6 | |
7 | while( (x = rand()) >= RAND_MAX - (RAND_MAX % UPPPER_BOUND) ) |
8 | ;
|
9 | return x % UPPPER_BOUND; |
10 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.