Primzahlen in Java generieren

Primzahlen in Java generieren

1. Einführung

In diesem Tutorial zeigen wir verschiedene Möglichkeiten, wie wir mit Java Primzahlen generieren können.

Wenn Sie überprüfen möchten, ob eine Zahl eine Primzahl ist, finden Sie hiera quick guide, wie das geht.

2. Primzahlen

Beginnen wir mit der Kerndefinition. A prime number is a natural number greater than one that has no positive divisors other than one and itself.

Zum Beispiel ist 7 eine Primzahl, weil 1 und 7 die einzigen positiven ganzzahligen Faktoren sind, wohingegen 12 nicht, weil es zusätzlich zu 1, 4 und 6 die Teiler 3 und 2 hat.

3. Primzahlen generieren

In diesem Abschnitt erfahren Sie, wie Sie effizient Primzahlen generieren können, die unter einem bestimmten Wert liegen.

3.1. Java 7 und früher - Brute Force

public static List primeNumbersBruteForce(int n) {
    List primeNumbers = new LinkedList<>();
    for (int i = 2; i <= n; i++) {
        if (isPrimeBruteForce(i)) {
            primeNumbers.add(i);
        }
    }
    return primeNumbers;
}
public static boolean isPrimeBruteForce(int number) {
    for (int i = 2; i < number; i++) {
        if (number % i == 0) {
            return false;
        }
    }
    return true;
}

Wie Sie sehen können, iteriertprimeNumbersBruteForce über die Zahlen von 2 bisn und ruft einfach die MethodeisPrimeBruteForce() auf, um zu überprüfen, ob eine Zahl eine Primzahl ist oder nicht.

Die Methode überprüft die Teilbarkeit jeder Zahl durch die Zahlen in einem Bereich von 2 bisnumber-1.

If at any point we encounter a number that is divisible, we return false. Am Ende, wenn wir feststellen, dass die Zahl durch keine ihrer vorherigen Zahlen teilbar ist, geben wir true zurück und geben an, dass es sich um eine Primzahl handelt.

3.2. Effizienz und Optimierung

Der bisherige Algorithmus ist nicht linear und hat die zeitliche Komplexität von O (n ^ 2). Der Algorithmus ist auch nicht effizient und es gibt eindeutig Raum für Verbesserungen.

Schauen wir uns die Bedingung in derisPrimeBruteForce()-Methode an.

Wenn eine Zahl keine Primzahl ist, kann diese Zahl in zwei Faktoren zerlegt werden, nämlicha undb, d.h. number = a * b. If both a and b were greater than the square root of n, a*b would be greater than n.

Mindestens einer dieser Faktoren muss kleiner oder gleich der Quadratwurzel einer Zahl sein. Um zu überprüfen, ob eine Zahl eine Primzahl ist, müssen wir nur auf Faktoren prüfen, die kleiner oder gleich der Quadratwurzel der zu überprüfenden Zahl sind.

Primzahlen können niemals eine gerade Zahl sein, da gerade Zahlen alle durch 2 teilbar sind.

Darüber hinaus können Primzahlen niemals eine gerade Zahl sein, da gerade Zahlen alle durch 2 teilbar sind.

Lassen Sie uns den Algorithmus unter Berücksichtigung der obigen Ideen verbessern:

public static List primeNumbersBruteForce(int n) {
    List primeNumbers = new LinkedList<>();
    if (n >= 2) {
        primeNumbers.add(2);
    }
    for (int i = 3; i <= n; i += 2) {
        if (isPrimeBruteForce(i)) {
            primeNumbers.add(i);
        }
    }
    return primeNumbers;
}
private static boolean isPrimeBruteForce(int number) {
    for (int i = 2; i*i < number; i++) {
        if (number % i == 0) {
            return false;
        }
    }
    return true;
}

3.3. Java verwenden 8

Mal sehen, wie wir die vorherige Lösung mit Java 8-Redewendungen umschreiben können:

public static List primeNumbersTill(int n) {
    return IntStream.rangeClosed(2, n)
      .filter(x -> isPrime(x)).boxed()
      .collect(Collectors.toList());
}
private static boolean isPrime(int number) {
    return IntStream.rangeClosed(2, (int) (Math.sqrt(number)))
      .filter(n -> (n & 0X1) != 0)
      .allMatch(n -> x % n != 0);
}

3.4. Verwendung von Sieat Of Eratosthenes

Es gibt noch eine weitere effiziente Methode, mit der wir Primzahlen effizient generieren können. Sie heißt Sieve Of Eratosthenes. Seine Zeiteffizienz ist O (n logn).

Werfen wir einen Blick auf die Schritte dieses Algorithmus:

  1. Erstellen Sie eine Liste aufeinanderfolgender Ganzzahlen von 2 bisn: (2, 3, 4,…, n)

  2. Zunächst seip gleich 2, der ersten Primzahl

  3. Zählen Sie abp in Schritten vonp und markieren Sie jede dieser Zahlen größer alsp selbst in der Liste. Diese Zahlen sind 2p, 3p, 4p usw .; Beachten Sie, dass einige von ihnen möglicherweise bereits markiert wurden

  4. Suchen Sie die erste Zahl größer alsp in der Liste, die nicht markiert ist. Wenn es keine solche Nummer gibt, hören Sie auf. Andernfalls lassen Siep jetzt gleich dieser Zahl (die die nächste Primzahl ist) und wiederholen Sie ab Schritt 3

Am Ende des Algorithmus sind alle nicht markierten Zahlen in der Liste die Primzahlen.

So sieht der Code aus:

public static List sieveOfEratosthenes(int n) {
    boolean prime[] = new boolean[n + 1];
    Arrays.fill(prime, true);
    for (int p = 2; p * p <= n; p++) {
        if (prime[p]) {
            for (int i = p * 2; i <= n; i += p) {
                prime[i] = false;
            }
        }
    }
    List primeNumbers = new LinkedList<>();
    for (int i = 2; i <= n; i++) {
        if (prime[i]) {
            primeNumbers.add(i);
        }
    }
    return primeNumbers;
}

3.5. Arbeitsbeispiel für Eratosthenes-Sieb

Mal sehen, wie es bei n = 30 funktioniert.

image

Betrachten Sie das obige Bild. Hier sind die Durchläufe, die der Algorithmus gemacht hat:

  1. Die Schleife beginnt mit 2, also lassen wir 2 unmarkiert und markieren alle Teiler von 2. Es ist im Bild mit der roten Farbe markiert

  2. Die Schleife bewegt sich zu 3, also lassen wir 3 unmarkiert und markieren alle Teiler von 3, die noch nicht markiert sind. Es ist im Bild mit der grünen Farbe markiert

  3. Die Schleife bewegt sich auf 4, sie ist bereits markiert, also fahren wir fort

  4. Die Schleife bewegt sich zu 5, also lassen wir 5 unmarkiert und markieren alle Teiler von 5, die noch nicht markiert sind. Es ist im Bild mit der violetten Farbe markiert

  5. Wir fahren mit den obigen Schritten fort, bis die Schleife erreicht ist, die der Quadratwurzel vonn entspricht

4. Fazit

In diesem kurzen Tutorial haben wir gezeigt, wie wir Primzahlen bis zum Wert 'N' generieren können.

Die Implementierung dieser Beispiele kannover on GitHub gefunden werden.