Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Randomize mehrmals starten (https://www.delphipraxis.net/104183-randomize-mehrmals-starten.html)

Chrissi91 28. Nov 2007 19:13


Randomize mehrmals starten
 
Hi,

endlich mal ein Thema, das es laut Suche noch nicht in der DP gab.

Unser Infolehrer hat behauptet, dass es nicht gut sei, mehrmals Randomize; zu schreiben.

Wie sieht es aus? Stimmmt das? Ich denke das is dem PC egal. ^^

DeddyH 28. Nov 2007 19:16

Re: Randomize mehrmals starten
 
Wozu den Zufallsgenerator mehrmals starten? Wenn mein Auto läuft, lass ich den Anlasser auch in Ruhe.

Dax 28. Nov 2007 19:18

Re: Randomize mehrmals starten
 
Es ist nicht gut. Wenn du das mehrmals machst, wird der Zufallsgenerator mehrmals neu initialisiert, und da Randomize auf Basis von GetTickCount und damit im Millisekunden-Bereich arbeitet... Nun, am besten ein Beispiel.
Delphi-Quellcode:
var a: Integer;

Randomize;
a := Random(1000);
Randomize;
a := a - Random(1000);
a wird nahezu immer 0 sein, da der Zufallsgenerator zwei mal initialisiert wird, und dies wahrscheinlich mit dem selben Seed (4 Calls brauchen keine Millisekunde)...

thkerkmann 28. Nov 2007 19:19

Re: Randomize mehrmals starten
 
Hi

Dem PC ist das sicherlich egal :-D

Aber:
Der Zufallszahlengenerator erzeugt eine gleichverteilte Reihe von Zufallszahlen, ab einem bestimmten Startwert.
Wenn dieser Startwert gleich ist, kommt auch immer die gleiche Reihe heraus. Das kann man leicht nachprüfen, indem man Randomize nicht aufruft.

Wenn jetzt innerhalb der Reihe Randomize erneut aufgerufen wird, wird praktisch eine neue Zufallsreihe begonnen, die die Gleichverteilung der ersten Reihe umwerfen KÖNNTE.
Ich sage KÖNNTE, nicht muss.

Wenn man es also statistisch ganz genau nehmen will, so sollte man Randomize nur einmal aufrufen.

Gruss

alzaimar 28. Nov 2007 20:14

Re: Randomize mehrmals starten
 
Zitat:

Zitat von Dax
... Randomize auf Basis von GetTickCount

GetSystemTime, um genau zu sein, kommt aber aufs Gleiche raus.

Mit dem Zufall ist das ja so eine Sache. Ich würde sagen, der Lehrer hat Recht, sich aber nicht 100% korrekt ausgedrückt.

Luckie 28. Nov 2007 20:36

Re: Randomize mehrmals starten
 
Und das Thema hatten wir schon im Forum: Hier im Forum suchenrandomize.

mimi 29. Nov 2007 17:29

Re: Randomize mehrmals starten
 
Der Lehrer hätte euch auch den Grund dafür nennen können.

Du kannst Randomize aufrufen aber nicht hintereinander, zeitversetzt...
z.b. bei einem Spiel rufst du einfach Randomize alle 60 Sekunden auf... oder so....

alzaimar 29. Nov 2007 17:33

Re: Randomize mehrmals starten
 
Zitat:

Zitat von mimi
z.b. bei einem Spiel rufst du einfach Randomize alle 60 Sekunden auf... oder so....

:gruebel: wozu soll das gut sein? Damit der Zufall noch zufälliger wird?

mimi 29. Nov 2007 18:05

Re: Randomize mehrmals starten
 
Du hast es erfasst *G*, ob es sin macht oder nicht ist ja eine andere Frage, aber es währe eine Möglichkeit.... oder nicht ?

Amateurprofi 29. Nov 2007 18:22

Re: Randomize mehrmals starten
 
Zitat:

Zitat von alzaimar
Zitat:

Zitat von mimi
z.b. bei einem Spiel rufst du einfach Randomize alle 60 Sekunden auf... oder so....

:gruebel: wozu soll das gut sein? Damit der Zufall noch zufälliger wird?

Das ist gut, weil man sonst (wenn Randomize nur einmal aufgerufen wird) unter bestimmten Voraussetzungen ohne große Probleme vorhersagen kann, welches die nächste "Zufallszahl" ist, wenn die ersten paar "Zufallszahlen" bekannt sind.

mimi 29. Nov 2007 18:24

Re: Randomize mehrmals starten
 
ach ? kannst du dazu mal ein kleines beispiel machen ?

Bei einem Spiel währe das bestimmt nicht besonder schlimm kommt aber auf das Spiel an.
mir ist aufgefallen wenn man Random in einem Timer aufruft zählt er nur hoch......

sirius 29. Nov 2007 18:27

Re: Randomize mehrmals starten
 
Zitat:

Zitat von Dax
Es ist nicht gut. Wenn du das mehrmals machst, wird der Zufallsgenerator mehrmals neu initialisiert, und da Randomize auf Basis von GetTickCount und damit im Millisekunden-Bereich arbeitet... Nun, am besten ein Beispiel.
Delphi-Quellcode:
var a: Integer;

Randomize;
a := Random(1000);
Randomize;
a := a - Random(1000);
a wird nahezu immer 0 sein, da der Zufallsgenerator zwei mal initialisiert wird, und dies wahrscheinlich mit dem selben Seed (4 Calls brauchen keine Millisekunde)...

Naja fast richtig. für solche Leute wie dich, hat sich Borland auch etwas ausgedacht und nimmt deswegen statt gettickcount QueryPerformancCounter. Da wird etwas fixer gezählt.
Du kannst diese Demonstration aber durchführen indem du die globale Variable RandSeed von Hand belegst.

Dax 29. Nov 2007 18:31

Re: Randomize mehrmals starten
 
Zitat:

Zitat von sirius
Naja fast richtig. für solche Leute wie dich, hat sich Borland auch etwas ausgedacht und nimmt deswegen statt gettickcount QueryPerformancCounter. Da wird etwas fixer gezählt.
Du kannst diese Demonstration aber durchführen indem du die globale Variable RandSeed von Hand belegst.

Ja, etwas mit den QP-Funktionen hatte ich noch im Hinterkopf, hatte es aber mit einem anderen Teil der RTL assoziert (nur warum?).

Neotracer64 29. Nov 2007 19:08

Re: Randomize mehrmals starten
 
Vielleicht ist es ja für einige interessant. :)
Hab das gerade mit OllyDbg rausgefunden.
Zumindest ist das so bei Delphi 7 Enterprise. (Build 4.453)

Delphi-Quellcode:
function PredictNextRandom(RSeed: PInteger; Range: Integer): Integer;
begin
  result := RSeed^ * $8088405 + 1;
  asm
    PUSH EDX
    MOV EAX, Range
    MUL result
    MOV result, EDX
    POP EDX
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
end;
Zitat:

Das ist gut, weil man sonst (wenn Randomize nur einmal aufgerufen wird) unter bestimmten Voraussetzungen ohne große Probleme vorhersagen kann, welches die nächste "Zufallszahl" ist, wenn die ersten paar "Zufallszahlen" bekannt sind.
PredictNextRandom, sagt die nächste Pseudozufallszahl IMMER voraus, egal wie häufig Randomize aufgerufen wurde. :D
Also im Prinzip egal, bzw. eher überflüssig Randomize häufiger aufzurufen.

alzaimar 29. Nov 2007 19:56

Re: Randomize mehrmals starten
 
Zitat:

Zitat von sirius
Naja fast richtig. für solche Leute wie dich, hat sich Borland auch etwas ausgedacht und nimmt deswegen statt gettickcount QueryPerformancCounter.

Naja, fast richtig. :mrgreen:
Bei Delphi 6 sehe ich in der System.Pas das hier
Delphi-Quellcode:
Procedure Randomize;
...
    CALL   GetSystemTime
...
Aber die CodeGear-Fuzzis haben doch etwas verändert, denn bei BDS2006 sehe ich das hier
Delphi-Quellcode:
Procedure Randomize;
...
if QueryPerformanceCounter(Counter) then
Zitat:

Zitat von Amateurprofi
Das ist gut, weil man sonst (wenn Randomize nur einmal aufgerufen wird) unter bestimmten Voraussetzungen ohne große Probleme vorhersagen kann, welches die nächste "Zufallszahl" ist, wenn die ersten paar "Zufallszahlen" bekannt sind.

Nun ja. Dann verwendet man aber eben nicht den Delphi-PRG, sondern einen etwas sicherererern, z.B. den Twister.

sirius 29. Nov 2007 20:34

Re: Randomize mehrmals starten
 
Zitat:

Zitat von Neotracer64
Hab das gerade mit OllyDbg rausgefunden.

Mit OllyDbg :gruebel: , man kann auch einfach in die System.Pas schauen ("_RandInt" zum Beispiel).


Zitat:

Zitat von alzaimar
Naja, fast richtig. :mrgreen:

:P

Neotracer64 29. Nov 2007 20:43

Re: Randomize mehrmals starten
 
Ne. Bei mir springt er immer auf "Unit System", wenn ich auf Random() "Strg+Mausklick" draufklicke.

EDIT: Ahh, jetz seh ichs. Wie biste auf RandInt_ gekommen. Einfach durchgekramt? :S

himitsu 29. Nov 2007 21:03

Re: Randomize mehrmals starten
 
Zitat:

Zitat von Neotracer64
EDIT: Ahh, jetz seh ichs. Wie biste auf RandInt_ gekommen. Einfach durchgekramt? :S

Gesucht? Der Delphi-Debugger verrät einem auch Dank der Debuginfos welche Funktion genau aufgerufen wird.
In diesem Fall RandInt und da die SystemInt etwas besonderes ist (PAS stimmt nicht mit ganz DCU überein), ist hier auch der Funktionsname nicht ganz stimmig, aber soein _ stört bei 'ner Suche ja nicht so sehr.

Und wen es interessiert, hier nochmal alles in Pascal
> http://www.delphipraxis.net/internal...=450466#450466
und die vorheriggen Seiten sind wohl auch nicht sooo uninteressant :angel:

sirius 29. Nov 2007 21:08

Re: Randomize mehrmals starten
 
Zitat:

Zitat von Neotracer64
Ne. Bei mir springt er immer auf "Unit System", wenn ich auf Random() "Strg+Mausklick" draufklicke.

EDIT: Ahh, jetz seh ichs. Wie biste auf RandInt_ gekommen. Einfach durchgekramt? :S

Du hast noch nicht häufig in der System.Pas gesucht :zwinker:

Neotracer64 29. Nov 2007 21:14

Re: Randomize mehrmals starten
 
*Autsch*
Danke ihr beiden.
Ich habe bis jetzt wirklich immer gedacht, alle diese Funktionen seien hardcoded im Compiler drin. oh wee oh wee.
Den Delphi Debugger benutze ich nicht so gerne, da bin ich zu sehr an Olly gewöhnt. :cyclops:

himitsu 29. Nov 2007 21:22

Re: Randomize mehrmals starten
 
Zitat:

Zitat von Neotracer64
Ich habe bis jetzt wirklich immer gedacht, alle diese Funktionen seien hardcoded im Compiler drin. oh wee oh wee.

So ganz Unrecht hast du auch garnicht. Bei vielen Dingen die Hardgecodet sind, wird als Ort auf die System-Unit verwiesen und nicht alles was in der System.pas drin steht, liegt auch wirklich in der System.dcu (die CompilerMagic ist halt ganz nett :roll: )

Zitat:

Zitat von Neotracer64
Den Delphi Debugger benutze ich nicht so gerne, da bin ich zu sehr an Olly gewöhnt. :cyclops:

Aber wenn man was über die Delphi-Interna rausbekommen möchte, dann ist der schon sehr Hilfreich :zwinker:

sirius 29. Nov 2007 21:27

Re: Randomize mehrmals starten
 
Zitat:

Zitat von himitsu
Bei vielen Dingen die Hardgecodet sind, wird als Ort auf die System-Unit verwiesen

Genau, und dann muss man einfach mal suchen.....

Amateurprofi 30. Nov 2007 01:45

Re: Randomize mehrmals starten
 
Zitat:

Zitat von mimi
ach ? kannst du dazu mal ein kleines beispiel machen ?
Bei einem Spiel währe das bestimmt nicht besonder schlimm kommt aber auf das Spiel an.
mir ist aufgefallen wenn man Random in einem Timer aufruft zählt er nur hoch...... .

@mimi:
Gern, siehe weiter unten.

Zitat:

Zitat von alzaimar
Nun ja. Dann verwendet man aber eben nicht den Delphi-PRG, sondern einen etwas sicherererern, z.B. den Twister..

@alzaimar:
Ich will dir ja nicht zu nahe treten, aber die ursprüngliche Frage war nicht, welchen Random-Generator man verwenden sollte,
sondern, ob man Randomize nur einmal aufrufen sollte.


Zitat:

Zitat von Neotracer64
Vielleicht ist es ja für einige interessant. :)
Hab das gerade mit OllyDbg rausgefunden.
Zumindest ist das so bei Delphi 7 Enterprise. (Build 4.453)

Delphi-Quellcode:
function PredictNextRandom(RSeed: PInteger; Range: Integer): Integer;
begin
  result := RSeed^ * $8088405 + 1;
  asm
    PUSH EDX
    MOV EAX, Range
    MUL result
    MOV result, EDX
    POP EDX
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
  ShowMessage(IntToStr(PredictNextRandom(@RandSeed,10)) + ' == '+ IntToStr(Random(10)));
end;
Zitat:

Das ist gut, weil man sonst (wenn Randomize nur einmal aufgerufen wird) unter bestimmten Voraussetzungen ohne große Probleme vorhersagen kann, welches die nächste "Zufallszahl" ist, wenn die ersten paar "Zufallszahlen" bekannt sind.
PredictNextRandom, sagt die nächste Pseudozufallszahl IMMER voraus, egal wie häufig Randomize aufgerufen wurde. :D
Also im Prinzip egal, bzw. eher überflüssig Randomize häufiger aufzurufen.


@Neotracer64:

Das ist doch keine Vorhersage.
Im Prinzip macht ihr doch nichts Anderes als zum Beispiel

var oldrs:integer;
oldrs:=randseed;
ShowMessage(IntToStr(Random(range));
randseed:=oldrs;

Was ich in meinem Kommentar weiter oben meinte, ist daß die nächsten "Zufallszahlen" vorhergesagt werden können ohne daß der aktuelle Wert von Randseed bekannt ist.
Die "bestimmten" Bedingungen, von denen ich sprach sind

1) Es wird die Random Funktion aus System benutzt, die auch in PredictNextRandom simuliert wird.
2) Der Algorithmus, mit dem der von Random gelieferte Wert in eine "Zufallszahl" umgewandelt wird, muß bekannt sein.
3) Zwischen den einzelnen Aufrufen von Random wird nicht Randomize aufgerufen.

Der unter (2) angesprochene Algorithmus, der eine Zahl im Bereich min bis max zurückgibt, könnte zum Beispiel so aussehen:
Delphi-Quellcode:
FUNCTION RandomNumber(min,max:integer):integer
begin
   result:=Random(max-min+1)+min;
end;
Wenn wir zum Beispiel "Zufallszahlen" im Bereich 10 bis 60 brauchen können wir dann die "Zufallszahlen" mit
ShowMessage(IntToStr(RandomNumber(10,60)))
ausgeben.

Ich behaupte nun, daß ich, wenn eine bestimmte Anzahl nacheinander erzeugter Zufallszahlen (in der Reihenfolge der Erzeugung) vorliegen, die nächsten Zahlen vorhersagen kann, ohne daß mir RandSeed bekannt ist.

Die Anzahl der Zahlen, die mindestens bekannt sein müssen ergibt sich zum Beispiel für Zahlen im Bereich 10 bis 60 mit
min:=10;
max:=60;
range:=max-min+1
count:=Trunc(LogN(range,$100000000))+1; // = 6

Ihr könnt mich gern testen.
1) Legt min und max fest. Beide müssen im Byte Bereich sein also 0 bis 255.
2) Notiert euch den Wert von RandSeed vor Erzeugung der ersten Zufallszahl (damit das später reproduzierbar ist)
3) Erzeugt mit der o.g. Funktion RandomNumber count+1 Zahlen (zur Sicherheit eine mehr als minimal erforderlich. (ich blamiere mich nicht so gern)
4) Stellt die count+1 Zahlen in die DP, aber bitte nicht den notierten Wert von RandSeed. Der Witz an der Sache ist ja gerade, daß ich den nicht brauche.

Und ich brauche dann ein paar Minuten um die nächsten Zahlen zu nennen.

Die Beschränkung, daß min und max im Byte Bereich liegen müssen ist, keine grundsätzliche Beschränkung.
Ich habe, wie es der Zufall so will, gerade vor ein paar Tagen begonnen, mich mit diesem Thema auseinanderzusetzen, und das Programm, daß die Vorhersage macht ist noch in der Entwicklung und deshalb (noch) auf den Byte Bereich beschränkt.

Bei Interesse schreibe ich gern einen kleinen Aufsatz, wie das funktioniert und stelle dann auch gern das Programm mit Source-Code in die DP. Das alles ist übrigens kein Hexenwerk, sondern eigentlich ganz simpel.

alzaimar 30. Nov 2007 06:35

Re: Randomize mehrmals starten
 
Zitat:

Zitat von Amateurprofi
@alzaimar:
Ich will dir ja nicht zu nahe treten, aber die ursprüngliche Frage war nicht, welchen Random-Generator man verwenden sollte,
sondern, ob man Randomize nur einmal aufrufen sollte.

:gruebel:
Wer Randomize mehrmals aufrufen möchte, um den Zufall noch zufälliger zu machen, der soll eben einen anderen PRG verwenden. Wieso sollte das weniger mit dem Thema zu tun haben, als Deine Ausführungen? Oder wolltest du einfach mal 'Hallo' sagen? :zwinker:

marabu 30. Nov 2007 07:07

Re: Randomize mehrmals starten
 
Moin,

ich habe mir den Opener nochmal durchgelesen und halte das für die Aufforderung zu einer lockeren Diskussion, die durchaus eine gewisse Breite einnehmen darf, ohne dass sie deshalb off topic wird.

Ich finde die Grundlagenarbeit von Klaus interessant. Die Bestimmung der Folgefunktion eines PRG ermöglicht Krypto-Attacken, aber das wusste Borland auch und warnte deshalb stets vor der Verwendung des eigenen PRG in einem Sicherheitskontext.

Die Erzeugung einer immer gleichen Folge von quasi zufälligen Zahlen ist übrigens kein Nachteil, sondern eine Entwurfseigenschaft. Die Reproduzierbarkeit ist durchaus gewollt. Der mehrmalige Aufruf von Randomize() stört lediglich die geplante Gleichverteilung der Zufallszahlen, macht den PRG aber deshalb nicht tauglicher für Verschlüsselungsalgorithmen.

Freundliche Grüße

Amateurprofi 30. Nov 2007 08:08

Re: Randomize mehrmals starten
 
Zitat:

Zitat von alzaimar
Zitat:

Zitat von Amateurprofi
@alzaimar:
Ich will dir ja nicht zu nahe treten, aber die ursprüngliche Frage war nicht, welchen Random-Generator man verwenden sollte,
sondern, ob man Randomize nur einmal aufrufen sollte.

:gruebel:
Wer Randomize mehrmals aufrufen möchte, um den Zufall noch zufälliger zu machen, der soll eben einen anderen PRG verwenden. Wieso sollte das weniger mit dem Thema zu tun haben, als Deine Ausführungen? Oder wolltest du einfach mal 'Hallo' sagen? :zwinker:

Weil ich mit meinen Ausführungen versuchte, eine Begründung zu liefern, warum man Randomize nicht nur einmal bei Programmstart aufrufen sollte, sondern immer dann, wenn eine Folge mehrerer Zufallszahlen geliefert werden soll.
Damit bin ich sehr direkt auf die Frage des Thread-Erstellers eingegangen.

QuickAndDirty 30. Nov 2007 09:01

Re: Randomize mehrmals starten
 
Also, statistisch gesehen wird die Zufallsfolge schlechter,
wenn du Randomize mehrmals startest ist das Auftraten einer
Zahl nicht mehr gleich wahrscheinlich gegen über dem anderer.

Wenn du also Rondomize mehrmals aufrufst hast du für die meisten
Anwendungen von Pseudozuall eher eine Verschlechterung als eine
Verbesserung des Zufalls.

Im übrigen gibt es auch echte Zufalls Generatoren, wie sie krypto-
Spezialisten benutzen. Diese produzieren Zufallszahlen durch das Messen
der Zahl der Zerfälle einer Radioaktiven Substanz und ähnliches.

Neotracer64 30. Nov 2007 12:46

Re: Randomize mehrmals starten
 
Zitat:

ohne daß der aktuelle Wert von Randseed bekannt ist.
Ok. Jetz versteh ich was du meinst.
Jetz mal ins Praktische überlegt:
Der RandSeed ist aber nur dann nicht bekannt, wenn er auf einem anderen Computer (dem Server) ausgeführt wird und die Zufallszahlen zum Client (zu mir) übertragen werden. Dann kann man deine Methode gut benutzen um "vorheruzusagen" (Eigentlich wird hier nirgendwo was vorausgesagt, "ausgerechnet" passt da wohl besser , da haste Recht).
Solange aber das Programm auf meinem Computer werkelt, kann ich immer auf den RandSeed im Speicher zugreifen, mache mir also nicht die Mühe das anders auszurechnen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:47 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