Problem mit Zufallszahlen-Generator
-
Random() wird mit aktueller Zeit initialisiert.
Es gibt aber auch einen Random(long seed) ctor, den musst du nehmen,
aber nicht in der Funktion pitch(), sondern ruhig im ctor.
Übergib doch einfach ein Die-Objekt und initialisiere r mit nextInt.Jockel
-
Hallo Leute,
erstmal danke für Euere Antworten!
Wenn ich es richtig verstanden habe, dann ist das Problem, dass die Instanzen von Random mit dem gleichen Wert initialisiert werden. Deswegen habe ich jetzt einfach eine statische Random-Variable für alle Würfel angelegt.
import java.util.Random ; public class Die { private int sides = 0 ; private static Random r = new Random () ; public Die (int v) { sides=v ; } int pitch () { return ((Math.abs(r.nextInt() % sides)) + 1) ; } }
Dass sollte die sauberste Lösung sein! Oder habe ich etwas übersehen?
Nochmals vielen Dank für die Hilfe!
Ciao
shoat
-
shoat schrieb:
Dass sollte die sauberste Lösung sein! Oder habe ich etwas übersehen?
ja, ist das die sauberste.
(die falle verrate ich nicht, ist zu unwahrscheinlich, daß sie zuschnappt)
-
volkard schrieb:
shoat schrieb:
Dass sollte die sauberste Lösung sein! Oder habe ich etwas übersehen?
ja, ist das die sauberste.
(die falle verrate ich nicht, ist zu unwahrscheinlich, daß sie zuschnappt)Hallo Volkard!
Jetzt hast Du mich schon neugierig gemacht. Wenn Du also die Zeit findest und Lust hast, dann würde ich gerne etwas mehr über die Falle erfahren.
Schließlich möchte ich diese Klasse in einem eigenen kleinen Freeware-Projekt einsetzen und es wäre doch tragisch, wenn irgendwann Fehler auftauchen und ich kann mir nicht erklären woher?
Vielen Dank!
Ciao
shoat
-
falls Random() nicht stark ist (ich weiß nicht, wie gut der zufallszahlengenerator dieser sprache ist), kannste die an sich tolle version kaputtmachen, wenn du öfters sachen wie
while(d.pitch()<98)
schreibst.
ins hauptgeschäft fallen danach nur noch die zahlen, die einer 99 oder 100 folgen und das kann bei nem kleinen zufallsraum sehr beengend werden. ist natürlich nur gefährlich, wenn Random schlecht ist. in diesem fall wären unabhängige zufallszahlengeneratoren besser.
-
Hallo Volkard,
zuerst nochmals Danke für Deinen Einsatz, aber ich verstehe die letzten Ausführungen nicht so richtig.
volkard schrieb:
falls Random() nicht stark ist (ich weiß nicht, wie gut der zufallszahlengenerator dieser sprache ist), ...
Ok, ich bin im klaren darüber, dass der Zufallszahlen-Generator nicht der tollste ist und dass sich die Zahlen wahrscheinlich (ich kenne den genauen Algorithmus nicht) zyklisch in einer Periode von 2^n (mit n ziemlich groß) wiederholen. Dies ist aber für meine Anwendung nicht so wichtig, da ich mit fast 100%iger Sicherheit sagen kann, dass ich Die.pitch() deutlich weniger als diese 2^n-mal aufrufen werde.
volkard schrieb:
...kannste die an sich tolle version kaputtmachen, wenn du öfters sachen wie
while(d.pitch()<98)
schreibst.
ins hauptgeschäft fallen danach nur noch die zahlen, die einer 99 oder 100 folgen und das kann bei nem kleinen zufallsraum sehr beengend werden. ist natürlich nur gefährlich, wenn Random schlecht ist.Ich weiß ehrlich gesagt nicht genau, was Du hier meinst. Wahrscheinlich ist mein Verstand gerade nicht anwesend. (*gähn* \me braucht mal wieder Schlaf) Vielleicht kannst Du mir ja nochmal ein wenig ausführlich erklären worauf Du hinaus willst. Danke dafür!
Ich habe jedenfalls durch Empirie herausgefunden, dass die erzeugten Zahlen wenigstens halbwegs normalverteilt sind (meint alle Zahlen, die Die.pitch() zurückgibt, kommen ungefähr gleich häufig vor). Dies war für mich der wichtigste Punkt - schließlich geht es bei meiner Anwendung auch um Wahrscheinlichkeitsrechnung (z. B. hier: die Wahrscheinlichkeit, dass eine Zahl auf einem Würfel gewürfelt wird, ist für jeden Zahl gleich).
volkard schrieb:
in diesem fall wären unabhängige zufallszahlengeneratoren besser.
Gerne! Bloß habe ich keine Ahnung (bin ja auch shoat == Anfänger, wie ich die mit java ansteuere, geschweige denn, dass ich einen unabhängigen, guten Zufallsgenerator kenne/besitze.
Ich würde mich gerne in diesem Punkt belehren lassen bzw. mich verbessern.
Viele Grüße!
Ciao
shoat
-
shoat schrieb:
Ich habe jedenfalls durch Empirie herausgefunden, dass die erzeugten Zahlen wenigstens halbwegs normalverteilt sind (meint alle Zahlen, die Die.pitch() zurückgibt, kommen ungefähr gleich häufig vor). Dies war für mich der wichtigste Punkt - schließlich geht es bei meiner Anwendung auch um Wahrscheinlichkeitsrechnung (z. B. hier: die Wahrscheinlichkeit, dass eine Zahl auf einem Würfel gewürfelt wird, ist für jeden Zahl gleich).
kannste mal messen, ob bei nem würfel mit einer million seiten die 0 sichtbar häufiger als die 999999 drankommt? wenn da nix schief wirkt, brauchste dir keine gedanken über nen besseren zufallszahlengenerator zu machen, dann ist deiner echt gut.
-
volkard schrieb:
kannste mal messen, ob bei nem würfel mit einer million seiten die 0 sichtbar häufiger als die 999999 drankommt? wenn da nix schief wirkt, brauchste dir keine gedanken über nen besseren zufallszahlengenerator zu machen, dann ist deiner echt gut.
Wenn die ints, die der Zufallsgenerator ausspuckt, gleichverteilt sind, dann sollte die 999999 etwas seltener vorkommen als die 0 (abgesehen davon, dass in dem Code da oben natürlich garkeine 0 entsteht). Das bringt das "%", das hier verwendet wird, wohl mit sich.
-
Eventuell hilft hier ja auch java.security.SecureRandom weiter... DEr sollte bessere Zufallszahlen liefern.
-
destruct0r schrieb:
Eventuell hilft hier ja auch java.security.SecureRandom weiter... DEr sollte bessere Zufallszahlen liefern.
Danke für die Idee. Ich habe mir eben mal die Klasse angeschaut. Ich denke, es ist fast schon ein zu großer Aufwand, wenn man nur eine halbwegs gleichverteilte Zufallszahl im Bereich von 0-n haben möchte. Für weitergehende Anwendungen werde ich die mögliche Verwendung auf jeden Fall prüfen.
Vielen Dank!
Ciao
shoat
-
volkard schrieb:
kannste mal messen, ob bei nem würfel mit einer million seiten die 0 sichtbar häufiger als die 999999 drankommt? wenn da nix schief wirkt, brauchste dir keine gedanken über nen besseren zufallszahlengenerator zu machen, dann ist deiner echt gut.
Ich habe eben ein paar Tests durchlaufen lassen. Es ist keine signifikante Abweichung festzustellen. Warum auch? (siehe auch unten)
Gregor schrieb:
Wenn die ints, die der Zufallsgenerator ausspuckt, gleichverteilt sind, dann sollte die 999999 etwas seltener vorkommen als die 0
Ich bin mir dessen bewußt! Ich denke, Du meinst folgendes Problem:
Beispiel (vereinfacht!):
Automatische Zufallszahlenerzeugung zz_10 im Bereich von 0-9 durch die Klasse Random. Annahme: Die Wahrscheinlichkeit für jeden Wert von 0-9 ist jeweils 0,1. Ich benötige nur Zufallszahlen zz_3 im Bereich von 0-3. Also rechne ich zz_3 = zz_10 % 4 ; Damit ist zz_3 = 0 für zz_10 == {0,4,8} zz_3 = 1 für zz_10 == {1,5,9} zz_3 = 2 für zz_10 == {2,6} zz_3 = 3 für zz_10 == {3,7} Damit ergibt sich folgende Wahrscheinlichkeitsverteilung für zz_3 == 0 0,3 für zz_3 == 1 0,3 für zz_3 == 2 0,2 für zz_3 == 3 0,2
Die Zahlen sind also nicht mehr wirklich zufällig. Es gibt es Präferenz zu den niedrigeren Zahlen!
Da allerdings die tatsächlich automatisch erzeugten Zufallszahlen (vgl. zz_10) im Bereich von Integer.MinValue (-2^31) bis Integer.MaxValue(2^31-1) und die von mir errechneten Zufallszahlen (vgl. zz_3) sehr klein bleiben, fällt die Verfälschung nicht besonders ins Gewicht.
Oder sollte ich vielleicht doch lieber die nextLong() anstatt von nextInt() benutzen? Was meint ihr?
Gregor schrieb:
(abgesehen davon, dass in dem Code da oben natürlich garkeine 0 entsteht). Das bringt das "%", das hier verwendet wird, wohl mit sich.
Um genau zu sein liegt es nicht an dem Modulo, sondern an dem +1 .
Vielen Dank!
Ciao
shoat