![]() |
randomize result ???
Hi,
ich hab in einem Programm eine Funktion die Zufallszahlen im Integer-Format erzeugt, ganz einfach über randomize und random. Diese Funktion wird aus einer anderen mehrmals aufgerufen, aber gibt immer das gleiche result aus :-( . Ich denke die Zufallsfunktion wird nur einmal ausgeführt und gibt dann immer ihr result zurück, ich brauch es aber unbedingt, dass sie mehrmals ausgeführt wird! Eben für verschiedene Zahlen. danke, Czapie. |
Re: randomize result ???
Zitat:
Poste doch mal die entscheidende Funktion. |
Re: randomize result ???
Hi,
Zitat:
Code:
Quelle : OH.
procedure Zufall;
var I: Integer; begin Randomize; for I := 1 to 50 do begin { Ausgabe an zufälligen Positionen im Fenster } Canvas.TextOut(Random(Width), Random(Height), 'Fang mich!'); end; end; Merke : vor jeder Zufallszahl randomize aufrufen :!: Sonst ist der Zufall ein gespeicherter. Gruß Hansa |
Re: randomize result ???
Zitat:
...:cat:... |
Re: randomize result ???
Zitat:
Also: randomize() nur einmal aufrufen. Das hat folgenden Grund: randomize() ermittelt einen Startwert für eine Zufallszahlenfolge. Mit diesem Startwert wird etwas getan, sodass sich eine möglichst nicht vorhersehbare Zahl daraus ergibt, jedoch ist die Operation, die mit dem Startwert getätigt wird, immer die gleiche. Jetzt kommt der Knackpunkt: randomize() ermittelt den Startwert anhand der aktuellen Uhrzeit. Ruft man randomize() schnell mehrmals hintereinander auf, ändert sich die Zeit nur so geringfügig, dass randomize() dies nicht registriert. Das bedeutet, dass man jedes Mal denselben Startwert bekommt, also auch dieselbe "Zufallszahl". Das ist definitiv nicht das, was man will. MfG, d3g |
hier kriege ich immer unterschiedliche Zahlen, Maximal-Wert 100 !
Code:
Gruß
procedure TForm1.Label1Click(Sender: TObject);
begin randomize; Label1.Caption := IntToStr (random (100)); end; Hansa |
Weil sich in der Zwischenzeit die Uhrzeit "grundlegend" ändert. Randomize wird über den internen Zeitgeber initialisiert. Wenn Du jedoch Randomize 100 Mal direkt nacheinander aufrufst und je eine Zufallszahl aus dem gleichen Bereich holst, dann ist der Zufall weg.
Delphi-Quellcode:
// ein form mit memo und button
procedure TForm1.Button1Click(Sender: TObject); var I: Integer; begin for I := 0 to 99 do begin Randomize; Memo1.Line.Add(IntToStr(Random(100))); end; end; |
Re: randomize result ???
Hi,
Zitat:
Gruß Hansa |
Der letzte Beitrag erklärt das Randomize-Problem
![]() |
Hi,
auf die Idee zu suchen bin ich noch gar nicht gekommen. :mrgreen: Daß es dazu etwas gibt, liegt fast auf der Hand. Aber das mit den 18tel Sekunden ? Ist das tatsächlich noch so ? Das habe ich noch in Erinnerung aus Urzeiten, 386er oder so. :shock: Sagenhaft! Trotzdem : das randomize steht wahrscheinlich nur an falscher Stelle. Gruß Hansa |
Stimmt, das ist aus den Uhrzeiten, aber nicht bloss 386er, sondern schon die 086er. Aber der Zeitgeber hat sich seit dem gehalten. Basiert glaube ich auf den Schwingungen irgendwelcher Quartze.
...:cat:... |
Re: randomize result ???
Hi,
@ Sakura : Sagenhaft, wie gesagt :shock: Ich kann es immer noch nicht fassen. Diese Zeittaktung kommt doch tatsächlich noch von dem IPM-Ur-PC (1980 ?? oder wann ?). Hierzu sei noch erwähnt, daß in Geldspielautomaten vielfach 486er CPUs stecken, wobei die Taktung eventuell wichtig ist und auch in DB-Fahrkartenautomaten. In den Spielautomaten hängt tatsächlich ein altes 486er - Motherboard senkrecht drin, der Automat war "Made in USA", typisch! Zitat:
Gruß Hansa |
Re: randomize result ???
Zitat:
|
Re: randomize result ???
Hallo,
Zitat:
WAAAAAAAHHHH - nein; eben das genau nicht. Es reicht, 'randomize' ein einziges Mal aufzurufen - beispielsweise während des Programmstarts. Danach musst Du nur noch 'random()' aufrufen, um die gewünschten (Pseudo-)Zufallszahlen zu erhalten. |
Re: randomize result ???
Hi,
Zitat:
Gruß Hansa |
!!!
Hi Leute,
erst mal danke für die rege Diskussion und die vielen Antworten, bin grad erst nach hause gekommen, werd noch nen bißchen probieren und dann schreiben wie's war, also wie richtig. Czapie. |
ok habs
Also,
so funktionierts: In FormCreate, oder OnCreate, wird das randomize eingetragen, und in der "Zufallsfunktion" dann immer random aufgerufen, and that works! Danke, schönes Weeki, Czapie. |
Hi Hansa,
ich glaube, du hast noch nicht ganz verstanden, was wir meinen. Angenommen, du schreibst (als einfaches Beispiel) ein Programm, das eine Lottoziehung simuliert. Dann brauchst du schnell 6 bzw. 7 Zufallszahlen hintereinander. Ein Code der so aussähe
Delphi-Quellcode:
liefert dir sieben mal die gleiche Zufallszahl, weil nämlich in der Regel auf heutigen Prozessoren so wenig Zeit vergeht, dass ein Achzehntelsekundenschritt nicht auftritt (selbst wenn, dann erhältst du zwei unterschiedliche Zahlen, das ist auch nicht, was du willst).
var
numbers: arrray[0..6] of Integer; procedure GetNumbers(); var i: Integer; begin for i := 0 to 6 do begin Randomize(); numbers[i] := Random(7) + 1; end; end; Folgender Code wäre richtiger:
Delphi-Quellcode:
Hier wird Randomize() nur einmal pro Ziehung aufgerufen, das heißt, du bekommst sieben verschiedene Pseudo-Zufallszahlen (die können zwar doppelt vorkommen, aber das Prinzip ist ja wohl klar). Wenn du GetNumbers() nicht oft hintereinander aufrufst, ist das okay.
procedure GetNumbers();
var i: Integer; begin Randomize(); for i := 0 to 6 do numbers[i] := Random(49) + 1; end; Der kleine Haken dabei ist nur: Randomize() braucht Rechenzeit - minimal aber trotzdem. Möglicherweise möchtest du aber auch tausend mal hintereinander GetNumbers() aufrufen. Dann musst du das natürlich anders machen:
Delphi-Quellcode:
Randomize() wird nur einmal aufgerufen, man bekommt 7000 "ungleiche" Pseudo-Zufallszahlen.
var
numbers: array[0..999][0..6] of Integer; procedure GetNumbers(element: Integer); var i: Integer; begin for i := 0 to 6 do numbers[element][i] := Random(49) + 1; end; procedure CallGetNumbers(); var i: Integer; begin Randomize(); for i := 0 to 999 do GetNumbers(i); end; Der Punkt ist, dass die letzte Möglichkeit in jedem Falle die beste ist, da sie am wenigsten rechenzeit braucht (da Randomize() nur einmal aufgerufen wird) und außerdem am wenigsten fehleranflällig ist. Daher ist es sinnvoll, immer diese Möglichkeit zu empfehlen. Also noch einmal ganz deutlich: Am besten ist es, Randomize() nur einmal im ganzen Programm aufzurufen. Am besten im Project-File (View|Project Source) oder, wenn man nur ein Formular benutzt, im OnCreate-Ereignis. MfG, d3g [edit]Hab ich wohl ein bisschen lange getippt... :mrgreen:[/edit] |
Moin Zusammen,
Zitat:
Die Zahlenfolge die Random ausgibt hängt direkt mit dem Wert in Randseed zusammen, so dass bei einem gleichen Wert für RandSeed die Zahlenfolge von Random auch immer die gleiche ist. Wer also immer die gleiche "zufällige" Zahlenfolge braucht setzt RandSeed auf immer den gleichen Wert. Auf Randomize kann man also im Prinzip verzichten, indem man RandSeed selber setzt. Mehrfaches Aufrufen von Randomize schadet also nur dann, wenn die Zeitdifferenz zwischen den Aufrufen zu klein ist, wie eben, z.b. in einer Schleife. Übrigens ist die Auflösung des Timers nicht eine 18tel Sekunde (0,0556 sek) sondern 18 Millisekunden (0,018 Sek). |
Zitat:
|
@Christian: Hab ich was anderes behauptet? :?
|
Moin d3g,
falls Du die grundsätzliche Funktionalität von Randomize meintest: Nein, hast Du nicht, ich hab's nur noch mal um das Warum ergänzt. Was mir gerade noch einfällt: Um etwas einmal pro Programmstart zu machen gäbe es auch noch die Möglichkeit den Aufruf in den initialization Abschnitt einer Unit zu legen. |
Zitat:
...:cat:... |
Irgendwie steht in diesem Thread alles doppelt und dreifach :mrgreen:...
Zitat:
|
Moin sakura,
es ging mir nur um eine weitere Möglichkeit. ;-) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:01 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz