Einzelnen Beitrag anzeigen

QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.884 Beiträge
 
Delphi 12 Athens
 
#136

Re: Random ist kein reiner Zufall

  Alt 5. Apr 2007, 15:06
Nachfolgend mal ein Beitrag aus google Groups
Das sollte dann wohl alle fragen beantworten.
Zitat:
Die einfachste und fuer sehr viele Zwecke ausreichende Methode ist die
sogenannte lineare Kongruenzmethode, die sich auf Rechnern leicht und schnell
implementieren laesst. Wir nehmen an, dass der Rechner z.b. mit Zahlen zwischen
0 und 2^32-1 rechnen kann.

Dann liefert die Formel

Seed_neu = (08088485h * Seed_alt + 1) mod 2^32

in Turbo-Pascal

var RandSeed:longint;

RandSeed := $08088405*RandSeed + 1;

eine Zahlenfolge, in denen saemtliche Werte zwischen 0 und 2^32-1 genau einmal
vorkommen und die sich dann wiederholt. Die Operation liefert also eine
Reihenfolge/Aufzaehlung/Permutation aller Zahlen 0..2^32-1. Diese Permutation
ist nachweislich recht "zufaellig". Um nachzuweisen, dass die Formel

Seed_neu = (c*Seed_alt + 1) mod 3^32

tatsaechlich alle Zahlen von 0..2^32-1 aufzaehlt und keine "vergisst", ist
nicht ganz einfach. Vor allem ist die Wahl von c nicht trivial. Man kann
zeigen, dass die Zahl c kongruent 5 modulo 8 sein muss, damit die obige Formel
fuer eine beliebige (!) 2-er-Potenz als Modul eine vollstaendige Permutation
0..Modul-1 liefert. c darf nicht zu gross und nicht zu klein sein, damit die
Folge dann "zufaellig" aussieht. Der obige Wert von c ist gut und wird z.b. von
der Funktion Random in Turbo-Pascal verwendet.

Die obige Folge liefert aber noch lange nicht das, was man unter einer
Zufallsfolge versteht, also z.B. unter einer zufaelligen Gleichverteilung der
Zahlen {0,1} oder allgemein {0,1,...,n-1}, denn sie ist zunaechst nur eine
Permutation, in der sich Werte nur nach 4 Milliarden Zuegen wiederholen. Dazu
muss man sie noch einer geeigneten Transformation unterwerfen, damit man nur
Werte aus {0..n-1} erhaelt, die sich dann natuerlich auch in kuerzeren
Abstaenden wiederholen sollen/muessen.

Dazu muessen hier die _hohen_ Bits von Seed "abgegriffen" werden.

Die Operation "Seed mod n" waere denkbar ungeeignet, denn sie liefert z.b. fuer
n=2 offensichtlich fuer aufeinanderfolgende Seed-Werte abwechselnd 0 und 1.

Die korrekte Transformation lautet hier

Seed := (c*Seed+1) mod 2^32
Random := (n*Seed) div 2^32 { Wert aus {0,...,n-1}

Sie sollte nur fuer maximal n=2^16 angewandt werden. D.h. fuer einen
"richtigen" Zufallszahlengenerator fuer 16-Bit-Werte braucht man einen
Zufallspermutationsgenerator von mindestens 32 Bit Laenge.

Dieser Algorithmus hat den Vorzug, dass er wahrscheinlich der
schnellstmoegliche sinnvolle Pseudeo-Zufalls-Algorithmus ist und er ist in den
meisten Compiler implementiert, die eine Zufallsfunktion bereitstellen (Basic,
Pascal,Fortran,C).

Um den Gererator bei Programmstart zu _initialisieren_ gibt es meist eine
Funktion namens Randomize, die ueblicherweise die Systemzeit ausliest und Seed
damit auf einen halbwegs nicht reproduzierberen und unerwarteten Wert setzt.
Wenn man die Zufallsfolge reproduzierbar sein soll, kann man Seed von Hand auf
einen beliebigen Wert setzen, den man sich merkt. Dann wird immer dieselbe
"Zufallsfolge" erzeugt. die Initialisierung sollte aber nur einmal geschehen,
da wiederholtes Randomize die Folge eher verschelchtert als verbessert.

Fuer sehr hohe Ansprueche gibt es erheblich kompliziertere und auch bessere
Pseudo-Zufallsgeneratoren.

cu
Horst
Da wo er einmal von "mod 3 " spricht ist wohl mod 2 gemeint.
hier die Quelle
http://groups.google.de/group/fido.g...81eb097e3b72d4

Noch etwas in Delphi kann auf mod 2^32 verzichtet werden da Variablen einfach überlaufen.
Andreas
Monads? Wtf are Monads?
  Mit Zitat antworten Zitat