Zufallszahlengenerator mit Startwert

Yogilein

Member
Leider erlaubt die Funktion Math.random() in Javascript keine Startwerte. Somit kann man eine einmal erzeugte Zufallszahlenreihe nicht wiederholen oder gar in einer anderen Sprache identisch ermitteln.

Vor geraumer Zeit habe ich daher eine kleine Funktion geschrieben, die Startwerte erlaubt und ganz einfach in andere Sprachen umgesetzt werden kann. Vielleicht kann sie hier jemand gebrauchen.

Anbei die Funktion mit entsprechenden Aufrufen zur Erläuterung.

Code:
<script type=text/javascript>

//Javascript kennt keine Zufallszahlen mit einem Startwert.
//Diesen braucht man z.B., wenn man mehrmals die gleichen
//Zufallszahlen erzeugen will.
//Oder man benötigt in verschiedenen Sprachen die gleichen
//Zufallszahlen, z.B. in Javascript und in PHP.
//Für solche Anwendungen habe ich diese kleine Funktion geschrieben.

//Variable definieren
var rand=0;
var min=1;
var max=100;

//Zufallszahl initialisieren und Startwert merken
startwert=random(0);

//Ein Beispiel für den Einsatz
//5 Zufallszahlen erzeugen und im Alert-Fenster ausgeben
alert("5 Zufallszahlen zwischen 1 und 100");
for(i=1;i<=5;i++){
  zufallszahl=Math.floor(random()*(max-min))+min;
  alert(zufallszahl);
}

//Jetzt die 5 gleichen Zufallszahlen erneut erzeugen (mit dem gemerkten Startwert initialisieren)
random(startwert);	
alert("Und jetzt noch ein Mal die 5 gleichen Zufallszahlen zwischen 1 und 100");
for(i=1;i<=5;i++){
  zufallszahl=Math.floor(random()*(max-min))+min;
  alert(zufallszahl);
}

//Und jetzt 5 neue Zufallszahlen ausgeben (mit 0 initialisieren)
random(0);
alert("Und jetzt 5 neue Zufallszahlen zwischen 1 und 100");
for(i=1;i<=5;i++){
  zufallszahl=Math.floor(random()*(max-min))+min;
  alert(zufallszahl);
}

//Die eigentliche Funktion
function random(z){
  var init_random=0;
  if(rand==0||z==0){
    init_random=1;
    var zeit=new Date();
    z=zeit.getMilliseconds();
    z=parseFloat("0."+String(z));
  }
  if(typeof(z)=="undefined")z=rand;
  z=z+Math.PI;
  z=Math.pow(z,8).toString();
  z=parseFloat("0."+z.substr(z.indexOf(".")+1,12));
  rand=z;
  if(init_random==1)random();
  return z;
}

</script>
 
Yogilein, da muss ein Missverständnis vorliegen!
//Oder man benötigt in verschiedenen Sprachen die gleichen
//Zufallszahlen, z.B. in Javascript und in PHP.
Wenn du irgend eine Angelegenheit auf der Annahme aufbaust, dass zwei verschiedene Systeme immer die gleichen Zufallszahlen erzeugen, dann ist es 1. keine Zufallszahl mehr sondern eine Pseudozufallszahl und eine Art Token-Generator und 2. keine besonders sichere Methode, da die Zahlenfolgen für jeden nachvollziehbar sind.
Lies mal bitte in diesem Artikel über den deterministischen Zufallszahlengenerator: Zufallszahlengenerator

Sag doch mal, wofür du so eine Struktur verwendest. Hoffentlich nicht für den Umgang mit schutzbedürftigen Informationen?
 
OK, dann hole ich mal ein bisschen aus.

I.d.R funktioniert jeder Zufallszahlengenerator mit einer Startzahl. Das ist eigentlich auch logisch, da etwas berechnet werden muss. Die Startzahl wird übrigens für jede zu generierende Zahl benötigt. Üblicherweise wird dabei die neue Startzahl aus der erzeugten Zufallszahl abgeleitet. Andere Verfahren (sicherlich nicht bei unseren Programmiersprachen) versuchen u.a. bestimmte Vorgänge in der Natur auszulesen, z.B. die Verteilung der Atome in der Luft.

Die meisten Programmiersprachen bieten den Startwert auch als Eingabe an.

Normalerweise wird hierzu ein Timerwert genommen. Ausgeklügelte Verfahren (sicherlich nicht in Javascript möglich) können zusätzlich auch noch die CPU-Auslastung, die CPU-Temperatur, die Speicherbelegung usw. berücksichtigen, da sich diese Werte permanent ändern.

Ziel der Zufallszahlen ist immer eine annähernd hohe Gleichverteilung in der Unendlichkeit. D.h, der Rechenalgorithmus darf nicht irgendwann (aufgrund der Startzahlen) immer das gleiche Ergebnis bringen oder einen Wert absolut bevorzugen oder vernachlässigen.

Und wann braucht man jetzt gleiche Zufallszahlen?

Das erste Mal bei mir war es, als ich von mehreren Spielern meines DOS-Spieles DIMONO den Wunsch bekam, dass man ein Spiel mit gleichen Vorgaben erneut spielen wollte, um zu sehen, ob man mit anderen Spielzügen besser abschneidet. Gut, ich hätte die Zufallszahlen in einem Array speichern können, aber einfacher war es, diese mit dem gleichen Startwert erneut zu erzeugen.

Das zweite Mal brauchte ich die gleichen Zufallszahlen bei der Simulation einer statistischen Umfrage. Ziel war zu ermitteln, was herauskommt, wenn 1000 Leute ihre Meinung (die übrigens eine Tendenz hatte) abgeben. Sind in 1000 Durchgängen größere Abweichungen zu erwarten? Da ich teilweise seltsame Ergebnisse hatte und diese, durch die immer neuen Zufallszahlen, nicht nachvollziehbar waren, konnte ich mir nur so helfen, dass ich mir zu jedem Ergebnis den Startwert merkte und die Abweichler dann mit den gleichen Zufallszahlen erneut durchspielte. Und so bin ich dann auf einen Programmierfehler gestoßen.

Auch aktuell in Javascript hatte ich so ein Problem. Bei einer durch Zufallszahlen animierten Bewegung, verließ das Objekt ab und zu das Spielfeld. Da dies recht selten passierte, konnte ich mir nur helfen, indem ich beim Auftreten dieses Fehlers die Animation mit den gleichen Zufallszahlen erneut durchspielte.

Und wann brauche ich die gleichen Zufallszahlen in 2 unterschiedlichen Sprachen?

Auf diese Idee bin ich vor gut 3 Jahren gekommen. Ich wollte ein Javascript-Spiel schreiben und als Anreiz Preise ausloben. Doch wie kann ich verhindern, dass die Punkte manipuliert werden?

Ich wollte daher folgendes machen:

In PHP wird ein Startwert erzeugt. Dieser wird an Javascript übergeben und gleichzeitig in eine Datenbank geschrieben.
In Javascript werden anhand dieses Starwertes die notwendigen Zufallszahlen erzeugt.
Am Ende des Spieles werden der Startwert, die einzelnen Züge und die Punkte übergeben.
PHP prüft nun, ob der Startwert gültig ist (in Datenbank vorhanden und nicht älter als xx Minuten) und löscht ihn.
Anschließend spielt PHP das Spiel mit dem Startwert (jetzt müssen die gleichen Zufallszahlen erzeugt werden) und den Zügen nach und errechnet die Punkte. Das geht relativ schnell, da keinerlei Grafikausgaben und Benutzereingaben vorhanden sind.
Wenn diese Punkte mit den übermittelten Punkten übereinstimmen, kann man mit größter Wahrscheinlichkeit davon ausgehen, dass nicht manipuliert wurde.

Das Ganze habe ich allerdings auf Eis gelegt, da meine Seite und meine Spiele aktuell noch zu unbekannt sind, als dass es sich rentieren würde.
 
Du hast nicht wirklich eine globale Variable, die dir den Zustand deines Zufallsgenerators speichert?!

PS: Ich wage zu bezweifeln, dass deine Pseudozufallszahlengenerator wirklich gleichverteilt und unkorreliert ist. Es gibt einen Grund, warum solche Sachen wieso der Mersenne Twister entwickelt wurden.
PPS: Spielmanipulationen kannst du einfacher verhindern, indem du die komplette Spiellogik auf dem Server stattfinden lässt und im Client wirklich nur die Darstellung und Nutzereingaben hast.
 
Zurück
Oben