2009-04-15 12 views
2

Ich versuche, eine Java-Implementierung des Park-Miller-Carta PRNG-Zufallszahlengenerators zu machen.Park-Miller-Carta PRNG Zufallsgenerator kehrt immer zurück 2.33E-10

Unten ist die Implementierung der Random-Funktion in ActionScript 3 from here.

return (_currentSeed = (_currentSeed * 16807) % 2147483647)/0x7FFFFFFF 
                  + 0.000000000233; 

Ich habe nicht viel Glück dies in Java zu arbeiten bekommen:

int seed = 20; //for example. 

public double random() { 
    seed = (seed * 16807) % 2147483647; 
    return seed/0x7FFFFFFF + 0.000000000233; 
} 

Diese immer 2.33E-10 zurückgibt. Irgendwelche Ideen, was ich in Java falsch mache? (der AS3-Code gibt 0.0001565276181885122 zurück, dann 0.6307557630963248 für die ersten beiden Antworten mit einem Seed von 20).

+0

Warum? Wenn es für Ihre eigene Erbauung ist, ist das eine Sache, aber für Produktionscode wirklich gut (dh kryptographisch sicher) ist Zufallszahlenerzeugung äußerst schwierig, richtig zu tun. Der RNG ist wahrscheinlich die größte technische Schwachstelle in den meisten Kryptosystemen. –

+0

@Chris UND Park-Miller-Carta ist ziemlich schlecht. – Varkhan

Antwort

6
seed/0x7FFFFFFF 

eine ganze Zahl Operation, da die beiden Argumente ganze Zahlen sind. Integer-Division rundet immer das "wahre" Ergebnis nach unten ab. In diesem Fall liegt das wahre Ergebnis zwischen 0 und 1, daher gibt die Operation immer 0 zurück.

Um ein Gleitkommaergebnis zu erhalten, muss mindestens eines der Argumente ein float sein, was folgendermaßen erreicht werden kann:

return (double)seed/0x7FFFFFFF + 0.000000000233; 
1

Replace:

return seed/0x7FFFFFFF+0.000000000233; 

mit:

return (double)seed/0x7FFFFFFF+0.000000000233; 
1

Operator Vorrang.

(seed/0x7FFFFFFF)+0.000000000233; 

ist, was Sie wirklich haben. Ist es das, was du meintest?

+0

Das hat der AS3-Code getan.Also ja, muss es sein. – Artelius

+1

Nein, die Vorrangregeln könnten anders sein. Auch die Semantik des Divisionsoperators kann unterschiedlich sein, was anscheinend geschehen ist. –

2

OK, also ist das wesentliche Problem, dass Sie Gleitkommadivision, nicht Ganzzahldivision machen müssen, wie andere hingewiesen haben.

Aber ich denke, das Fixieren dieses bestimmten Codes ist eine Art neben dem Punkt. Warum sollte man sich überhaupt damit beschäftigen? Es ist im Wesentlichen die gleiche Klasse von Algorithmus ist java.lang.Random!

Wenn Sie einen schnellen Generator wünschen, denken Sie an XORShift generator. Wenn Sie einen Generator von guter Qualität wünschen, haben Sie SecureRandom out of the box (obwohl es viel langsamer ist), beachten Sie den Numerical Recipes Algorithmus (ein ziemlich schneller, kombinierter Generator), den Sie in Java wie folgt implementieren könnten:

public class HighQualityRandom extends Random { 

    private Lock l = new ReentrantLock(); 
    private long u; 
    private long v = 4101842887655102017L; 
    private long w = 1; 

    public HighQualityRandom() { 
    this(System.nanoTime()); 
    } 
    public HighQualityRandom(long seed) { 
    l.lock(); 
    u = seed^v; 
    nextLong(); 
    v = u; 
    nextLong(); 
    w = v; 
    nextLong(); 
    l.unlock(); 
    } 

    @Override 
    public long nextLong() { 
    l.lock(); 
    try { 
     u = u * 2862933555777941757L + 7046029254386353087L; 
     v ^= v >>> 17; 
     v ^= v << 31; 
     v ^= v >>> 8; 
     w = 4294957665L * (w & 0xffffffff) + (w >>> 32); 
     long x = u^(u << 21); 
     x ^= x >>> 35; 
     x ^= x << 4; 
     return (x + v)^w; 
    } finally { 
     l.unlock(); 
    } 
    } 

    protected int next(int bits) { 
    return (int) (nextLong() >>> (64-bits)); 
    } 

} 

Dies wird von einem Code kopiert, wo ich es gleichzeitig benötigt; Sie könnten das Schloss im Prinzip loswerden oder einfach die normale Synchronisation verwenden.

Wenn Sie unbedingt darauf bestehen, Park-Miller-Carta zu verwenden, würde ich es zumindest in eine Random-Unterklasse einbinden und java.util.Random dafür sorgen, dass Ints in Doubles umgerechnet werden - das ist es schließlich erweiterbare Bibliotheken in einer objektorientierten Sprache sind für ...