RANDOM und RANDOMIZE

25. September 2007 14:35

Hallo allerseits.

Kann es sein, dass der Navision Zufallsgenerator ziemlich "schlecht" ist?

Ich hab folgendes festgestellt:
Wenn man mit

RANDOM(6)

einen Zufallswert zwischen 1 und 6 erzeugen läß, bekommt man als Ergebnis immer 1,3 oder 5. 2, 4 und 6 wird nie ermittelt.

Liegt das an meinem Rechner oder ist das bei euch auch so?

Ich hab mal ne Schleife mit 1.000.000 Durchläufe gemacht, annähernde Gleichverteilung auf den ungeraden Werten, die geraden kommen nie.
Egal ob man vor jedem RANDOM noch ein RANDOMIZE vorschaltet, oder nicht.

25. September 2007 15:11

Korrektur,

das Problem tritt nur auf, wenn vor jedem RANDOM ein RANDOMIZE ausgeführt wird.

Trotzdem sehr seltsam.

25. September 2007 15:17

Äääääh... nicht ganz.
RANDOMIZE ist ja dazu da (übrigens in so ziemlich allen Programmiersprachen, die den Befehl kennen), um den "Zufallsbereich zu initialisieren" und wird EINMALIG vor dem allerersten RANDOM aufgerufen.
Wie du schon selber erkannt hast, darfst du nicht vor jedem RANDOM RANDOMIZE erneut aufrufen.

In der Onlinehilfe steht zu RANDOMIZE[Seed] u.a.:
Onlinehilfe hat geschrieben:Seed = A number RANDOMIZE uses to create a unique set of numbers. If you use the same number as seed, you get the same set of numbers generated.

25. September 2007 15:20

Versuchs mal so...

Code:

evaluate(i,copystr(format(time),7));
randomize(i);
message(format(random(6)));



ist zwar ein bisschen zusammengeschustert, aber sollte funktionieren.

Willst Du ein Würfelspiel programmieren? :lol:
hab ich auch schonmal gemacht... allerdings nich in navision :oops:

25. September 2007 15:34

Ich finde es trotzdem seltsam, da auch nach einmaligem Ausführen von RANDOMIZE der erste RANDOM(6) grundsätzlich immer 1,3 oder 5 liefert.

Nein ich wollte kein Würfelspiel programmieren, wäre aber mal einen Versuch wert. ;-)

Ich wollte eigentlich eine Multiple Choice Prüfung für unsere Azubis erstellen mit Zufallsgenierierten Fragen aus einem Fragenkatalog.

Re: RANDOM und RANDOMIZE

24. Juli 2012 16:46

rkaufmann hat geschrieben:Ich finde es trotzdem seltsam, da auch nach einmaligem Ausführen von RANDOMIZE der erste RANDOM(6) grundsätzlich immer 1,3 oder 5 liefert.

Nein ich wollte kein Würfelspiel programmieren, wäre aber mal einen Versuch wert. ;-)

Ich wollte eigentlich eine Multiple Choice Prüfung für unsere Azubis erstellen mit Zufallsgenierierten Fragen aus einem Fragenkatalog.


Nur weil ich gerade zufällig wegen einem anderen Beitrag auf diesen "alten" Beitrag gestossen bin...

Randomize() ohne Parameter nimmt automatisch die Zeit im Millisekunden als "Seed", man muss hier sich nicht selber andere sich ändernde Zahlen generieren lassen.

Wenn der Parameter (Seed) immer konstant ist kommen auch immer die selben Zufallszahlen raus.
In den meisten Fällen (bis ca. 10.000 Zufallszahlen) sollte die Uhrzeit aber ausreichend gute Zufallszahlen liefern.

Für Simulationen mit beispielsweise 100.000.000 "guten" Zufallszahlen sollte man sich andere Pseudo-Zufallszahlengeneratoren implemetieren.

mfg,
winfy
Zuletzt geändert von winfy am 25. Juli 2012 10:19, insgesamt 2-mal geändert.

Re: RANDOM und RANDOMIZE

24. Juli 2012 17:59

Weil es hier gerade noch mal aufgegriffen wurde. Ich habe damals bei meinen Tests festgestellt, dass das erste RANDOM nach einem RANDOMIZE bei mir immer ungerade Zahlen ermittelt und z. B. der 101te nur gerade Zahlen liefert... Als ich mir das dann noch ein wenig angeschaut habe ist mir aufgefallen, dass beim dritten Aufruf der RANDOM-Funktion tatsächlich ein zufälliger Wert herauszukommen scheint. Also habe ich seither immer drei RANDOM-Aufrufe nach einem RANDOMIZE eingebaut. :roll:

Re: RANDOM und RANDOMIZE

25. Juli 2012 08:14

Dazu ein Zusatz: Das macht er aber nur, wenn man eine gerade Zahl als Seed im Randomize mit gibt :)

Re: RANDOM und RANDOMIZE

25. Juli 2012 08:58

Nein, das macht er nur, wenn man eine gerade Zahl als Parameter für RANDOM angibt.
Der Seed im RANDOMIZE spielt dabei überhaupt keine Rolle.

Ich hab da diverse Tests mit 100.000 Zufallszahlen gemacht und dabei immer mit RANDOMIZE() gearbeitet, also dem Default Seed.
Wenn der Parameter am RANDOM eine gerade Zahl ist, ist die erste Zufallszahl immer eine ungerade Zahl.

Wenn du also eine Schleife baust wie die hier bekommst du als Zufallszahl immer nur ungerade Zahlen:

Code:
for i := 1 to 100000 do begin
  RANDOMIZE();
  x := RANDOM(6);
  .....
end;

Re: RANDOM und RANDOMIZE

25. Juli 2012 09:45

rkaufmann hat geschrieben:Nein, das macht er nur, wenn man eine gerade Zahl als Parameter für RANDOM angibt.
Der Seed im RANDOMIZE spielt dabei überhaupt keine Rolle.

Ich hab da diverse Tests mit 100.000 Zufallszahlen gemacht und dabei immer mit RANDOMIZE() gearbeitet, also dem Default Seed.
Wenn der Parameter am RANDOM eine gerade Zahl ist, ist die erste Zufallszahl immer eine ungerade Zahl.

Wenn du also eine Schleife baust wie die hier bekommst du als Zufallszahl immer nur ungerade Zahlen:


Args, du hast recht! :shock:
Das er so schlecht ist hätte ich auch nicht vermutet.

Es hilft auch nichts ihm einen eigenen Seed zu geben...

mfg,
winfy

Re: RANDOM und RANDOMIZE

25. Juli 2012 09:53

Eben, der Seed ist in dem Szenario völlig egal.

Die RANDOM Funktion ist einfach schlecht implementiert, was aber in einem ERP auch nicht wirklich Prio 1 hat.
Wenn das jemand wirklich produktiv braucht, sollte man da eher auf ein .NET Objekt oder was anderes "externes" zurückgreifen.
Hab mich damit aber auch nicht mehr im Detail weiterbeschäftigt.

Re: RANDOM und RANDOMIZE

25. Juli 2012 10:26

meto89 hat geschrieben:Weil es hier gerade noch mal aufgegriffen wurde. Ich habe damals bei meinen Tests festgestellt, dass das erste RANDOM nach einem RANDOMIZE bei mir immer ungerade Zahlen ermittelt und z. B. der 101te nur gerade Zahlen liefert... Als ich mir das dann noch ein wenig angeschaut habe ist mir aufgefallen, dass beim dritten Aufruf der RANDOM-Funktion tatsächlich ein zufälliger Wert herauszukommen scheint. Also habe ich seither immer drei RANDOM-Aufrufe nach einem RANDOMIZE eingebaut. :roll:


Hallo Meto,

das scheint wohl auf die schnelle eine Lösung zu sein.
Ich hatte allerdings schon nach dem 2. Random augenscheinlich Pseudozufallszahlen, aber ich habe da natürlich keine statistischen Verfahren angewendet um das zu prüfen.

mfg,
winfy

Re: RANDOM und RANDOMIZE

25. Juli 2012 17:06

Für alle die das Vertrauen in die Random-Funktion von Navision verloren haben folgende Alternative:

Ich habe einmal einen gängigen Pseudozufallszahlengenerator implementiert der akzeptable statistisch gesicherte Werte liefert und ihn ein wenig an die Randomfunktion im Navision angepasst. Eine Seed Variable müsste hier allerdings global angelegt werden. Ich habe daher bewusst auf setter und getter verzichtet.

Quelle: Steve K. Park and Keith W. Miller "Random Number Generators: Good ones are hard to find”

Randomize2(VAR Seed : Integer)
Code:
//generiert auf Basis von GUID-Werten einen Seed zwischen 1 und 2.147.483.646.
//bigseed ist vom Typ BigInteger
EVALUATE(bigseed, COPYSTR(DELCHR(CREATEGUID(),'=','{}-ABCDEF'),1,10));
Seed:= (bigseed MOD 2147483646) +1;


Random2(VAR Seed : Integer;Number : Integer) : Integer
Code:
//......................................................................................................
//Code: Minimal Standard Pseudozufallszahlengenerator (linearer Kongruenzgenerator)
//Quelle: Steve K. Park and Keith W. Miller "Random Number Generators: Good ones are hard to find", 1988
//Sprache: Navision C/AL (modifiziert von winfy)
//Limit: nur für 32 Bit signed Integer geeignet, erzeugt Pseudozufallszahlen von 1 bis Parameter "Number"
//......................................................................................................

//Definitionen
//a,m,q,r sind Variablen/Konstanten vom Typ Integer
//test, hi, lo sind Variablen vom Typ Integer
//Seed als Übergabeparameter vom Typ Integer

//Initialisierung der Werte
a := 16807; //alternativ a:= 48271;
m := 2147483647;
q := 127773; //alternativ q:= 44488;
r := 2836; //alternativ r:= 3399

//alternative "gute" Werte (L'Ecuyer)
//a := 39373;
//m := 2147483647;
//q := 54542;
//r := 1481;

//Pseudozufallszahl berechnen
hi := Seed DIV q;
lo := Seed MOD q; 
test := a * lo - r * hi;

//positiven Wertebereich sicherstellen
IF test > 0 THEN Seed := test
  ELSE Seed := test + m;

//Ergebnis im Bereich 1 bis Number erzeugen
IF (Number > 0) THEN EXIT((Seed MOD Number) + 1)
  ELSE EXIT(1); //alternativ EXIT(0) oder Fehlermeldung

Den Seed müsste man sich am Anfang selber berechnen oder man nimmt testweise meine Randomize2 Funktion.

mfg,
winfy