2017-10-23 2 views
4

Ich habe einen sehr einfachen linearen Kongruenzgenerator erstellt (oder zumindest denke ich, dass ich ihn habe), aber er gibt einige verrückte Werte einschließlich negativer Zahlen zurück. Ich kann nicht für das Leben von mir herauszufinden, warum, jede Hilfe sehr willkommen. Mein Code ist unten:Warum gibt mein Zufallszahlengenerator negative Werte zurück?

public static void main(String[] args) { 
    Scanner scanner = new Scanner(System.in); 
    long a = 252149039; 
    int c = 11; 
    long m =(long) Math.pow(2, 48); 
    long seed = System.currentTimeMillis(); 
    System.out.println("How many Random numbers would you like to get?"); 
    int number = scanner.nextInt(); 
    for (int i = 0; i <= number;i++) { 
     seed = ((a*seed)+c) % m; 
     System.out.println(seed); 
    } 
    scanner.close(); 
} 
+0

Nie "roll your own" Krypto oder RNG. Verwenden Sie eine vertrauenswürdige Bibliothek und befolgen Sie deren Anweisungen sorgfältig. –

Antwort

1

Weil System.currentTimeMillis() die aktuelle Zeit in Millisekunden zurückgibt.
So kann es große Zahlen wie 1508797287829 zurückgeben.

Multiplizieren einer Zahl wie 1508797287829 durch 252149039 (= 380441786171888746331):

... 
long a = 252149039; 
long seed = System.currentTimeMillis(); 
... 
seed = ((a*seed)+c) % m; 

erzeugt einen Überlauf für die Variable als long seedLong.MAX_VALUE als 2^63 - 1 definiert (= 9223372036854775807).


Um eine beliebige genaue ganze Zahl darstellen, Sie BigInteger nutzen könnten.
Beachten Sie, dass die Klasse unveränderlich ist.

Sie könnten seed als BigInteger deklarieren.

BigInteger seed = BigInteger.valueOf(System.currentTimeMillis()); 

Und auf diese Weise verwenden:

seed = seed.multiply(BigInteger.valueOf(a)) 
      .add(BigInteger.valueOf(c)) 
      .mod(BigInteger.valueOf(m)); 
+0

können Sie mir zeigen, wie man das korrigiert? Ich denke, ich kann bigInteger verwenden, aber ich bin mir nicht sicher, wie ich das machen soll. –

+0

Es ist in der Tat ein Weg. Ich habe es mit einem Beispiel aktualisiert. Beachten Sie, dass Sie 'mod()' und 'rest()' haben, um den Modulo zu berechnen. In Ihrem Anwendungsfall, in dem Sie keine negativen Zahlen haben können, sollten sie dasselbe Verhalten haben. – davidxxx

1

Sie erhalten Überlauffehler. A java int lang kann nur Werte bis zu 2^63-1 halten, alles, was größer ist als das Wraps. Die Mechanik, wie diese Arbeit befassen sich mit Zweierkomplement-Integer-Darstellung, und die kürzeste fix wäre

seed = seed >= 0 ? seed : seed + m 

nur hinzufügen, bevor Sie Samen drucken.

Verwandte Themen