Wie erstelle ich das kompakteste Mapping n → isprime (n) bis zu einer Grenze N?


152

Natürlich bool isprime(number)würde es eine Datenstruktur geben, die ich abfragen könnte.
Ich definiere den besten Algorithmus als den Algorithmus, der eine Datenstruktur mit dem niedrigsten Speicherverbrauch für den Bereich (1, N] erzeugt, wobei N eine Konstante ist.
Nur ein Beispiel für das, wonach ich suche: Ich könnte jede ungerade Zahl darstellen mit einem Bit, zB für den angegebenen Zahlenbereich (1, 10], beginnt bei 3:1110

Das folgende Wörterbuch kann mehr zusammengedrückt werden, oder? Ich könnte mit etwas Arbeit ein Vielfaches von fünf eliminieren, aber Zahlen, die mit 1, 3, 7 oder 9 enden, müssen im Array der Bits vorhanden sein.

Wie löse ich das Problem?


3
Ihre Anfrage ist etwas vage. Sie geben eine Signatur, die eine einzelne Zahl testet, fragen dann aber nach einer Datenstruktur von (1, N]. Möchten Sie einen Algorithmus, der ein Wörterbuch <int, bool> generiert, oder nur eine One-Shot-Funktion, die prüft, ob eine einzelne Zahl vorhanden ist ist Prime?
Michael Haren

@ Michael Entschuldigung, das ist die beste Beschreibung, die ich finden konnte. Was ich suche, ist genau so, wie Sie sagen: ein boolesches Wörterbuch. Ich möchte den Platz im Wörterbuch minimieren. Danke :)
AraK

1
Wenn es das ist, wonach Sie suchen, wurde es bereits gefragt: stackoverflow.com/questions/1032427/…
Ben S

14
Sie müssten die NSA
Charles Bretana

Antworten:


79

Es gibt viele Möglichkeiten, den Primalitätstest durchzuführen .

Es gibt nicht wirklich eine Datenstruktur, die Sie abfragen können. Wenn Sie viele Zahlen testen müssen, sollten Sie wahrscheinlich einen Wahrscheinlichkeitstest durchführen, da diese schneller sind, und anschließend einen deterministischen Test durchführen , um sicherzustellen, dass die Zahl eine Primzahl ist.

Sie sollten wissen, dass die Mathematik hinter den schnellsten Algorithmen nichts für schwache Nerven ist.


4
Miller-Rabin ist zunächst ein beliebter schneller Wahrscheinlichkeitstest.
qwr

214

Der schnellste Algorithmus für allgemeine Primetests ist AKS . Der Wikipedia-Artikel beschreibt es ausführlich und verweist auf das Originalpapier.

Wenn Sie große Zahlen finden möchten, suchen Sie nach Primzahlen mit speziellen Formen wie Mersenne-Primzahlen .

Der Algorithmus, den ich normalerweise implementiere (leicht zu verstehen und zu codieren), lautet wie folgt (in Python):

def isprime(n):
    """Returns True if n is prime."""
    if n == 2:
        return True
    if n == 3:
        return True
    if n % 2 == 0:
        return False
    if n % 3 == 0:
        return False

    i = 5
    w = 2

    while i * i <= n:
        if n % i == 0:
            return False

        i += w
        w = 6 - w

    return True

Es ist eine Variante des klassischen O(sqrt(N))Algorithmus. Es wird die Tatsache verwendet, dass eine Primzahl (außer 2 und 3) von Form ist 6k - 1oder 6k + 1nur Teiler dieser Form betrachtet.

Manchmal, wenn ich wirklich Geschwindigkeit will und die Reichweite begrenzt ist , implementiere ich einen Pseudo-Prime-Test, der auf dem kleinen Satz von Fermat basiert . Wenn ich wirklich mehr Geschwindigkeit will (dh den O (sqrt (N)) -Algorithmus insgesamt vermeiden möchte), berechne ich die falsch positiven Ergebnisse vor (siehe Carmichael- Zahlen) und führe eine binäre Suche durch. Dies ist bei weitem der schnellste Test, den ich jemals durchgeführt habe. Der einzige Nachteil ist, dass die Reichweite begrenzt ist.


7
Zwei Fragen: Können Sie erklären , besser , was die Variablen iund wsind, und was durch die Form gemeint ist , 6k-1und 6k+1? Vielen Dank für Ihren Einblick und das Codebeispiel (das ich zu verstehen versuche)
Freedom_Ben

6
@Freedom_Ben Los geht's, quora.com/…
Alan Dong

6
Wäre es nicht besser, das sqrtvon neinmal zu berechnen und damit zu vergleichen i, als i * ijeden Zyklus der Schleife zu berechnen ?
Pedros

3
@Dschoni ... aber Sie können nicht die schnellste Implementierung in die Kommentarfelder hier passen, um sie mit uns zu teilen?
GreenAsJade

3
Es schlägt für Nummer 1 fehl :(
Damjan Pavlica

27

Die beste Methode ist meiner Meinung nach, das zu verwenden, was vorher gegangen ist.

Es gibt Listen der ersten NPrimzahlen im Internet mit einer NLänge von mindestens fünfzig Millionen . Laden Sie die Dateien herunter und verwenden Sie sie. Es ist wahrscheinlich viel schneller als jede andere Methode, die Sie entwickeln werden.

Wenn Sie einen tatsächlichen Algorithmus wollen für die eigenen Primzahlen zu machen, hat Wikipedia allerlei gute Sachen auf Primzahlen hier , einschließlich Links zu den verschiedenen Methoden , es zu tun, und Prime Test hier , beide wahrscheinlichkeitsbasierte und schnellen deterministischen Methoden.

Es sollte eine konzertierte Anstrengung geben, die ersten Milliarden (oder sogar mehr) Primzahlen zu finden und sie irgendwo im Internet zu veröffentlichen, damit die Leute aufhören können, immer und immer wieder denselben Job zu machen und ... :-)


2
@hamedbh: Interessant. Haben Sie versucht, diese Dateien herunterzuladen? Es scheint, dass sie nicht existieren.
Paxdiablo

Noch nicht, fürchte ich: Ich habe während meiner Mittagspause nur schnell gesucht. Ich werde diesen Link löschen, falls etwas Bösartiges daran ist. Tut mir leid, ich hätte es wirklich zuerst überprüfen sollen.
Hamed

1
Solche Listen tun exist. Ich habe sie vor Jahren gesehen, aber nie daran interessiert, sie herunterzuladen. Die Wahrheit ist, dass sie (relativ gesehen) viel Platz beanspruchen und nicht in Programmen enthalten sein sollten, die man verkauft oder vertreibt. Darüber hinaus werden sie immer und für immer unvollständig sein. Es ist sinnvoller, jede Zahl zu testen, die während der Verwendung eines Programms in der Praxis auftaucht, da auf diese Weise weit weniger getestet werden als die Länge einer Liste, die Sie möglicherweise besitzen. Ich denke auch, dass pax den Zweck von Primalgorithmen meistens nicht erkennt, die Effizienz / Geschwindigkeit zu testen, anstatt tatsächlich Primzahlen zu finden.
CogitoErgoCogitoSum

2
@CogitoErgoCogitoSum, stimme zu, dass die Liste aller Primzahlen für immer veraltet sein wird, da ich den mathematischen Beweis gesehen habe, dass ihre Anzahl unendlich ist. Es ist jedoch xunwahrscheinlich, dass die Liste der ersten Primzahlen unvollständig ist, sobald sie erstellt wurde :-)
paxdiablo

1
Stimmt, aber es gibt bessere Speichermethoden als das lineare Lesen aus einer Datei. Wenn Sie wirklich aus einem gespeicherten Satz vorgenerierter Primzahlen lesen möchten, versuchen Sie es mit einer komplizierteren Datenstruktur, die das Problem beschleunigt.
CogitoErgoCogitoSum

10
bool isPrime(int n)
{
    // Corner cases
    if (n <= 1)  return false;
    if (n <= 3)  return true;

    // This is checked so that we can skip 
    // middle five numbers in below loop
    if (n%2 == 0 || n%3 == 0) return false;

    for (int i=5; i*i<=n; i=i+6)
        if (n%i == 0 || n%(i+2) == 0)
           return false;

    return true;
}

Dies ist nur eine C ++ - Implementierung des obigen AKS-Algorithmus


1
Es ist einer der effizientesten deterministischen Algorithmen, auf die ich gestoßen bin, ja, aber es ist keine Implementierung von AKS. Das AKS-System ist viel neuer als der beschriebene Algorithmus. Es ist wohl effizienter, aber aufgrund potenziell astronomisch großer Fakultäts- / Binomialkoeffizienten etwas schwierig zu implementieren.
CogitoErgoCogitoSum

Wie unterscheidet sich das von Derri Leahis (Nicht-) Antwort (außer C anstelle von Java)? Wie antwortet das What is the algorithm that produces a data structure with lowest memory consumption for the range (1, N]?
Graubart

1
Wie entspricht (n% i == 0 || n% (i + 2) == 0) 6n + 1 & 6n-1?
Yesh

@YeshwanthVenkatesh: Ein How does (n%i == 0 || n%(i+2) == 0) correspond to 6n+1 & 6n-1?Teil der Antwort besteht aus verschiedenen Rollen n, der andere ist 6n + 1 & 6n-1, was (6n-1) +0 & (6n-1) + 2 * entspricht.
Graubart

Beachten Sie auch, dass dieser Algorithmus nicht das richtige Ergebnis für 5und liefert 7.
Athan Clark

7

Ich habe die Effizienz der beliebtesten Vorschläge verglichen, um festzustellen, ob eine Zahl eine Primzahl ist. Ich habe python 3.6weiter gemacht ubuntu 17.10; Ich habe mit Zahlen bis zu 100.000 getestet (Sie können mit größeren Zahlen testen, indem Sie meinen Code unten verwenden).

Dieses erste Diagramm vergleicht die Funktionen (die weiter unten in meiner Antwort erläutert werden) und zeigt, dass die letzten Funktionen beim Erhöhen der Zahlen nicht so schnell wachsen wie die ersten.

plot1

Und in der zweiten Darstellung können wir sehen, dass bei Primzahlen die Zeit stetig wächst, aber Nicht-Primzahlen nicht so schnell wachsen (weil die meisten von ihnen frühzeitig eliminiert werden können).

plot2

Hier sind die Funktionen, die ich verwendet habe:

  1. Diese Antwort und diese Antwort schlugen ein Konstrukt vor, das Folgendes verwendet all():

    def is_prime_1(n):
        return n > 1 and all(n % i for i in range(2, int(math.sqrt(n)) + 1))
    
  2. Diese Antwort verwendete eine Art while-Schleife:

    def is_prime_2(n):
        if n <= 1:
            return False
        if n == 2:
            return True
        if n == 3:
            return True
        if n % 2 == 0:
            return False
        if n % 3 == 0:
            return False
    
        i = 5
        w = 2
        while i * i <= n:
            if n % i == 0:
                return False
            i += w
            w = 6 - w
    
        return True
    
  3. Diese Antwort enthielt eine Version mit einer forSchleife:

    def is_prime_3(n):
        if n <= 1:
            return False
    
        if n % 2 == 0 and n > 2:
            return False
    
        for i in range(3, int(math.sqrt(n)) + 1, 2):
            if n % i == 0:
                return False
    
        return True
    
  4. Und ich habe ein paar Ideen aus den anderen Antworten in eine neue gemischt:

    def is_prime_4(n):
        if n <= 1:          # negative numbers, 0 or 1
            return False
        if n <= 3:          # 2 and 3
            return True
        if n % 2 == 0 or n % 3 == 0:
            return False
    
        for i in range(5, int(math.sqrt(n)) + 1, 2):
            if n % i == 0:
                return False
    
        return True
    

Hier ist mein Skript zum Vergleichen der Varianten:

import math
import pandas as pd
import seaborn as sns
import time
from matplotlib import pyplot as plt


def is_prime_1(n):
    ...
def is_prime_2(n):
    ...
def is_prime_3(n):
    ...
def is_prime_4(n):
    ...

default_func_list = (is_prime_1, is_prime_2, is_prime_3, is_prime_4)

def assert_equal_results(func_list=default_func_list, n):
    for i in range(-2, n):
        r_list = [f(i) for f in func_list]
        if not all(r == r_list[0] for r in r_list):
            print(i, r_list)
            raise ValueError
    print('all functions return the same results for integers up to {}'.format(n))

def compare_functions(func_list=default_func_list, n):
    result_list = []
    n_measurements = 3

    for f in func_list:
        for i in range(1, n + 1):
            ret_list = []
            t_sum = 0
            for _ in range(n_measurements):
                t_start = time.perf_counter()
                is_prime = f(i)
                t_end = time.perf_counter()

                ret_list.append(is_prime)
                t_sum += (t_end - t_start)

            is_prime = ret_list[0]
            assert all(ret == is_prime for ret in ret_list)
            result_list.append((f.__name__, i, is_prime, t_sum / n_measurements))

    df = pd.DataFrame(
        data=result_list,
        columns=['f', 'number', 'is_prime', 't_seconds'])
    df['t_micro_seconds'] = df['t_seconds'].map(lambda x: round(x * 10**6, 2))
    print('df.shape:', df.shape)

    print()
    print('', '-' * 41)
    print('| {:11s} | {:11s} | {:11s} |'.format(
        'is_prime', 'count', 'percent'))
    df_sub1 = df[df['f'] == 'is_prime_1']
    print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
        'all', df_sub1.shape[0], 100))
    for (is_prime, count) in df_sub1['is_prime'].value_counts().iteritems():
        print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
            str(is_prime), count, count * 100 / df_sub1.shape[0]))
    print('', '-' * 41)

    print()
    print('', '-' * 69)
    print('| {:11s} | {:11s} | {:11s} | {:11s} | {:11s} |'.format(
        'f', 'is_prime', 't min (us)', 't mean (us)', 't max (us)'))
    for f, df_sub1 in df.groupby(['f', ]):
        col = df_sub1['t_micro_seconds']
        print('|{0}|{0}|{0}|{0}|{0}|'.format('-' * 13))
        print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
            f, 'all', col.min(), col.mean(), col.max()))
        for is_prime, df_sub2 in df_sub1.groupby(['is_prime', ]):
            col = df_sub2['t_micro_seconds']
            print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
                f, str(is_prime), col.min(), col.mean(), col.max()))
    print('', '-' * 69)

    return df

Ausführen der Funktion compare_functions(n=10**5)(Zahlen bis zu 100.000) Ich erhalte folgende Ausgabe:

df.shape: (400000, 5)

 -----------------------------------------
| is_prime    | count       | percent     |
| all         |     100,000 |     100.0 % |
| False       |      90,408 |      90.4 % |
| True        |       9,592 |       9.6 % |
 -----------------------------------------

 ---------------------------------------------------------------------
| f           | is_prime    | t min (us)  | t mean (us) | t max (us)  |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1  | all         |        0.57 |        2.50 |      154.35 |
| is_prime_1  | False       |        0.57 |        1.52 |      154.35 |
| is_prime_1  | True        |        0.89 |       11.66 |       55.54 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2  | all         |        0.24 |        1.14 |      304.82 |
| is_prime_2  | False       |        0.24 |        0.56 |      304.82 |
| is_prime_2  | True        |        0.25 |        6.67 |       48.49 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3  | all         |        0.20 |        0.95 |       50.99 |
| is_prime_3  | False       |        0.20 |        0.60 |       40.62 |
| is_prime_3  | True        |        0.58 |        4.22 |       50.99 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4  | all         |        0.20 |        0.89 |       20.09 |
| is_prime_4  | False       |        0.21 |        0.53 |       14.63 |
| is_prime_4  | True        |        0.20 |        4.27 |       20.09 |
 ---------------------------------------------------------------------

compare_functions(n=10**6)Wenn ich dann die Funktion ausführe (Zahlen bis zu 1.000.000), erhalte ich folgende Ausgabe:

df.shape: (4000000, 5)

 -----------------------------------------
| is_prime    | count       | percent     |
| all         |   1,000,000 |     100.0 % |
| False       |     921,502 |      92.2 % |
| True        |      78,498 |       7.8 % |
 -----------------------------------------

 ---------------------------------------------------------------------
| f           | is_prime    | t min (us)  | t mean (us) | t max (us)  |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1  | all         |        0.51 |        5.39 |     1414.87 |
| is_prime_1  | False       |        0.51 |        2.19 |      413.42 |
| is_prime_1  | True        |        0.87 |       42.98 |     1414.87 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2  | all         |        0.24 |        2.65 |      612.69 |
| is_prime_2  | False       |        0.24 |        0.89 |      322.81 |
| is_prime_2  | True        |        0.24 |       23.27 |      612.69 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3  | all         |        0.20 |        1.93 |       67.40 |
| is_prime_3  | False       |        0.20 |        0.82 |       61.39 |
| is_prime_3  | True        |        0.59 |       14.97 |       67.40 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4  | all         |        0.18 |        1.88 |      332.13 |
| is_prime_4  | False       |        0.20 |        0.74 |      311.94 |
| is_prime_4  | True        |        0.18 |       15.23 |      332.13 |
 ---------------------------------------------------------------------

Ich habe das folgende Skript verwendet, um die Ergebnisse zu zeichnen:

def plot_1(func_list=default_func_list, n):
    df_orig = compare_functions(func_list=func_list, n=n)
    df_filtered = df_orig[df_orig['t_micro_seconds'] <= 20]
    sns.lmplot(
        data=df_filtered, x='number', y='t_micro_seconds',
        col='f',
        # row='is_prime',
        markers='.',
        ci=None)

    plt.ticklabel_format(style='sci', axis='x', scilimits=(3, 3))
    plt.show()


6

Man kann Sympy verwenden .

import sympy

sympy.ntheory.primetest.isprime(33393939393929292929292911111111)

True

Aus Sympy-Dokumenten. Der erste Schritt ist die Suche nach trivialen Faktoren, die, wenn sie gefunden werden, eine schnelle Rückkehr ermöglichen. Wenn das Sieb groß genug ist, verwenden Sie als nächstes die Halbierungssuche für das Sieb. Für kleine Zahlen wird eine Reihe deterministischer Miller-Rabin-Tests mit Basen durchgeführt, von denen bekannt ist, dass sie keine Gegenbeispiele in ihrem Bereich aufweisen. Wenn die Anzahl größer als 2 ^ 64 ist, wird schließlich ein starker BPSW-Test durchgeführt. Während dies ein wahrscheinlicher Primetest ist und wir glauben, dass Gegenbeispiele existieren, sind keine Gegenbeispiele bekannt


Ein Algorithmus ist eine Folge genau definierter Schritte, die eine abstrakte Lösung für ein Problem definieren. - Was ist die denkbare Abfolge von Schritten im dargestellten Code? Was ist das memory consumption?
Graubart

2
@ Greybeard. Aus Sympy-Dokumenten. Der erste Schritt ist die Suche nach trivialen Faktoren, die, wenn sie gefunden werden, eine schnelle Rückkehr ermöglichen. Wenn das Sieb groß genug ist, verwenden Sie als nächstes die Halbierungssuche für das Sieb. Für kleine Zahlen wird eine Reihe deterministischer Miller-Rabin-Tests mit Basen durchgeführt, von denen bekannt ist, dass sie keine Gegenbeispiele in ihrem Bereich aufweisen. Wenn die Anzahl größer als 2 ^ 64 ist, wird schließlich ein starker BPSW-Test durchgeführt. Während dies ein wahrscheinlicher Primetest ist und wir glauben, dass Gegenbeispiele existieren, sind keine Gegenbeispiele bekannt.
LetzerWille

6

In Python 3:

def is_prime(a):
    if a < 2:
        return False
    elif a!=2 and a % 2 == 0:
        return False
    else:
        return all (a % i for i in range(3, int(a**0.5)+1))

Erklärung: Eine Primzahl ist eine Zahl, die nur durch sich selbst und 1 teilbar ist. Beispiel: 2,3,5,7 ...

1) wenn a <2: wenn "a" kleiner als 2 ist, ist es keine Primzahl.

2) elif a! = 2 und a% 2 == 0: Wenn "a" durch 2 teilbar ist, ist es definitiv keine Primzahl. Aber wenn a = 2 ist, wollen wir das nicht bewerten, da es eine Primzahl ist. Daher ist die Bedingung a! = 2

3) Alle zurückgeben (a% i für i im Bereich (3, int (a 0,5) +1)): ** Schauen Sie sich zuerst an, was der Befehl all () in Python tut. Ausgehend von 3 teilen wir "a" bis zu seiner Quadratwurzel (a ** 0,5). Wenn "a" teilbar ist, ist die Ausgabe False. Warum Quadratwurzel? Sagen wir a = 16. Die Quadratwurzel von 16 = 4. Wir müssen nicht bis 15 auswerten. Wir müssen nur bis 4 prüfen, um zu sagen, dass es keine Primzahl ist.

Extra: Eine Schleife zum Auffinden aller Primzahlen innerhalb eines Bereichs.

for i in range(1,100):
    if is_prime(i):
        print("{} is a prime number".format(i))

1
Wie unterscheidet sich das von der Antwort von Oleksandr Shmyheliuk ? (Beide verpassen einen "Schritt 2" in range()...)
Greybeard

1
Wenn eine Zahl gerade ist, ist sie keine Primzahl (außer 2). Sie müssen also nicht nach geraden Zahlen suchen. Dies ist viel schneller, wenn Sie eine Primzahl innerhalb eines Bereichs erhalten möchten. Die geraden Zahlen werden direkt ausgeschlossen.
Deep Growal


3

Bei großen Zahlen können Sie nicht einfach naiv prüfen, ob die Kandidatennummer N durch keine der Zahlen kleiner als sqrt (N) teilbar ist. Es stehen viel mehr skalierbare Tests zur Verfügung, beispielsweise der Miller-Rabin-Primalitätstest . Unten haben Sie die Implementierung in Python:

def is_prime(x):
    """Fast implementation fo Miller-Rabin primality test, guaranteed to be correct."""
    import math
    def get_sd(x):
        """Returns (s: int, d: int) for which x = d*2^s """
        if not x: return 0, 0
        s = 0
        while 1:
            if x % 2 == 0:
                x /= 2
                s += 1
            else:
                return s, x
    if x <= 2:
        return x == 2
    # x - 1 = d*2^s
    s, d = get_sd(x - 1)
    if not s:
        return False  # divisible by 2!
    log2x = int(math.log(x) / math.log(2)) + 1
    # As long as Riemann hypothesis holds true, it is impossible
    # that all the numbers below this threshold are strong liars.
    # Hence the number is guaranteed to be a prime if no contradiction is found.
    threshold = min(x, 2*log2x*log2x+1)
    for a in range(2, threshold):
        # From Fermat's little theorem if x is a prime then a^(x-1) % x == 1
        # Hence the below must hold true if x is indeed a prime:
        if pow(a, d, x) != 1:
            for r in range(0, s):
                if -pow(a, d*2**r, x) % x == 1:
                    break
            else:
                # Contradicts Fermat's little theorem, hence not a prime.
                return False
    # No contradiction found, hence x must be a prime.
    return True

Sie können es verwenden, um große Primzahlen zu finden:

x = 10000000000000000000000000000000000000000000000000000000000000000000000000000
for e in range(1000):
    if is_prime(x + e):
        print('%d is a prime!' % (x + e))
        break

# 10000000000000000000000000000000000000000000000000000000000000000000000000133 is a prime!

Wenn Sie zufällige Ganzzahlen testen, möchten Sie wahrscheinlich zuerst testen, ob die Kandidatennummer durch eine der Primzahlen teilbar ist, die kleiner als beispielsweise 1000 sind, bevor Sie Miller-Rabin aufrufen. Auf diese Weise können Sie offensichtliche Nicht-Primzahlen wie 10444344345 herausfiltern.


Dies ist der Miller-Test. Der Miller-Rabin-Test ist die probabilistische Version, bei der zufällig ausgewählte Basen getestet werden, bis ein ausreichendes Vertrauen erreicht ist. Außerdem hängt der Miller-Test nicht direkt von der Riemann-Hypothese ab, sondern von der Generalisierten Riemann-Hypothese (GRH) für quadratische Diriclet-Zeichen (ich weiß, dass es ein Schluck ist, und ich verstehe es auch nicht). Dies bedeutet, dass ein möglicher Beweis für die Riemann-Hypothese möglicherweise nicht einmal für die GRH gilt und daher den Miller-Test nicht als richtig erweist. Ein noch schlimmerer Fall wäre natürlich, wenn die GRH widerlegt wird.
Arne Vogel

2

Viel zu spät zur Party, aber ich hoffe das hilft. Dies ist relevant, wenn Sie nach großen Primzahlen suchen:

Um große ungerade Zahlen zu testen, müssen Sie den Fermat-Test und / oder den Miller-Rabin-Test verwenden.

Diese Tests verwenden eine modulare Exponentiation, die ziemlich teuer ist. Für die nBit-Exponentiation benötigen Sie mindestens eine ngroße int-Multiplikation undn Big-Int-Division. Dies bedeutet, dass die Komplexität der modularen Exponentiation O (n³) beträgt.

Bevor Sie die großen Waffen einsetzen, müssen Sie einige Testabteilungen durchführen. Aber mach es nicht naiv, es gibt eine Möglichkeit, sie schnell zu machen. Multiplizieren Sie zuerst so viele Primzahlen, wie in die Wörter passen, die Sie für die großen ganzen Zahlen verwenden. Wenn Sie 32-Bit-Wörter verwenden, multiplizieren Sie 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 = 3234846615 und berechnen Sie den größten gemeinsamen Divisor mit der Zahl, die Sie mit dem euklidischen Algorithmus testen. Nach dem ersten Schritt wird die Zahl unter die Wortgröße reduziert und der Algorithmus fortgesetzt, ohne vollständige große Ganzzahldivisionen durchzuführen. Wenn die GCD! = 1 ist, bedeutet dies, dass eine der Primzahlen, die Sie miteinander multipliziert haben, die Zahl teilt, sodass Sie den Beweis haben, dass es sich nicht um eine Primzahl handelt. Fahren Sie dann mit 31 * 37 * 41 * 43 * 47 = 95041567 usw. fort.

Sobald Sie mehrere hundert (oder tausend) Primzahlen auf diese Weise getestet haben, können Sie 40 Runden Miller-Rabin-Test durchführen, um zu bestätigen, dass die Zahl eine Primzahl ist. Nach 40 Runden können Sie sicher sein, dass die Zahl eine Primzahl ist. Es besteht nur eine Wahrscheinlichkeit von 2 ^ -80 nicht (es ist wahrscheinlicher, dass Ihre Hardware nicht richtig funktioniert ...).


1

Ich habe eine Primfunktion, die bis (2 ^ 61) -1 funktioniert. Hier:

from math import sqrt
def isprime(num): num > 1 and return all(num % x for x in range(2, int(sqrt(num)+1)))

Erläuterung:

Die all()Funktion kann folgendermaßen neu definiert werden:

def all(variables):
    for element in variables:
        if not element: return False
    return True

Die all()Funktion durchläuft nur eine Reihe von Bools / Zahlen und gibt zurück, Falsewenn 0 oder angezeigt wird False.

Die sqrt()Funktion macht nur die Quadratwurzel einer Zahl.

Beispielsweise:

>>> from math import sqrt
>>> sqrt(9)
>>> 3
>>> sqrt(100)
>>> 10

Der num % xTeil gibt den Rest von num / x zurück.

Schließlich range(2, int(sqrt(num)))bedeutet dies, dass eine Liste erstellt wird , die bei 2 beginnt und bei endetint(sqrt(num)+1)

Weitere Informationen zur Reichweite finden Sie auf dieser Website !

Der num > 1Teil prüft nur, ob die Variable numgrößer als 1 ist, da 1 und 0 nicht als Primzahlen betrachtet werden.

Ich hoffe das hat geholfen :)


Bitte argumentieren Sie, wie dies ein the bestAlgorithmus ist oder sogar ein guter .
Graubart

@greybeard, Die meisten Primfunktionen hier gehen nicht auf (2 ^ 31) -1 oder dauern zu lange für hohe Zahlen, aber meine funktioniert bis (2 ^ 61) -1, sodass Sie überprüfen können, ob eine Zahl eine Primzahl mit einer breiteren ist Zahlenbereich.
WhyAreYouReadingThis

1

In Python:

def is_prime(n):
    return not any(n % p == 0 for p in range(2, int(math.sqrt(n)) + 1))

Eine direktere Konvertierung vom mathematischen Formalismus zu Python würde alle verwenden (n% p! = 0 ...) , aber dies erfordert eine strikte Bewertung aller Werte von p. Die nicht beliebige Version kann vorzeitig beendet werden, wenn ein True-Wert gefunden wird.


Wrt "all (n% p! = 0 ...), aber das erfordert eine strikte Auswertung aller Werte von p" - das ist falsch. anyund allwerden beide früh verlassen . Also am ersten pwo n % pist 0, allwürde aussteigen.
Aneroid

1

bester Algorithmus für Primes Number Javascript

 function isPrime(num) {
      if (num <= 1) return false;
      else if (num <= 3) return true;
      else if (num % 2 == 0 || num % 3 == 0) return false;
      var i = 5;
      while (i * i <= num) {
        if (num % i == 0 || num % (i + 2) == 0) return false;
        i += 6;
      }
      return true
    }

1
import math
import time


def check_prime(n):

    if n == 1:
        return False

    if n == 2:
        return True

    if n % 2 == 0:
        return False

    from_i = 3
    to_i = math.sqrt(n) + 1

    for i in range(from_i, int(to_i), 2):
        if n % i == 0:
            return False
    return True

1

Eine Primzahl ist eine beliebige Zahl, die nur durch 1 und sich selbst teilbar ist. Alle anderen Zahlen werden als Verbund .

Der einfachste Weg, eine Primzahl zu finden, besteht darin, zu überprüfen, ob die eingegebene Zahl eine zusammengesetzte Zahl ist:

    function isPrime(number) {
        // Check if a number is composite
        for (let i = 2; i < number; i++) {
            if (number % i === 0) {
                return false;
            }
        }
        // Return true for prime numbers
        return true;
    }

Das Programm muss den Wert von numberdurch alle ganzen Zahlen von 1 bis zu seinem Wert teilen . Wenn diese Zahl nicht nur durch eins und sich selbst gleichmäßig geteilt werden kann, handelt es sich um eine zusammengesetzte Zahl.

Der Anfangswert der Variablen i muss 2 sein, da sowohl Primzahlen als auch zusammengesetzte Zahlen gleichmäßig durch 1 geteilt werden können.

    for (let i = 2; i < number; i++)

Dann iist weniger als numberaus dem gleichen Grund. Sowohl Primzahlen als auch zusammengesetzte Zahlen können gleichmäßig voneinander geteilt werden. Daher gibt es keinen Grund, dies zu überprüfen.

Dann prüfen wir mit dem Restoperator, ob die Variable gleichmäßig aufgeteilt werden kann.

    if (number % i === 0) {
        return false;
    }

Wenn der Rest Null ist, bedeutet dies, dass er numbergleichmäßig geteilt werden kann, also eine zusammengesetzte Zahl ist und false zurückgibt.

Wenn die eingegebene Zahl die Bedingung nicht erfüllt, bedeutet dies, dass es sich um eine Primzahl handelt und die Funktion true zurückgibt.


1
(Während ich denke, simplesteine gültige Interpretation von best :) Die Frage ist, was ist der beste Algorithmus, um zu überprüfen, ob eine Zahl eine Primzahl ist? : Ist es number / 2 < i < numbervorteilhaft, die Teilbarkeit zu prüfen ? Was ist mit number < i*i? Was sagen die verständlichen der anderen 3³ Antworten?
Graubart

1

Lassen Sie mich Ihnen die perfekte Lösung für 64-Bit-Ganzzahlen vorschlagen. Entschuldigung, C # zu verwenden. Sie haben es in Ihrem ersten Beitrag noch nicht als Python angegeben. Ich hoffe, Sie können eine einfache modPow-Funktion finden und leicht analysieren.

public static bool IsPrime(ulong number)
{
    return number == 2 
        ? true 
        : (BigInterger.ModPow(2, number, number) == 2 
            ? (number & 1 != 0 && BinarySearchInA001567(number) == false) 
            : false)
}

public static bool BinarySearchInA001567(ulong number)
{
    // Is number in list?
    // todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
    // Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}

0

Kleinste Erinnerung? Dies ist nicht klein, aber ein Schritt in die richtige Richtung.

class PrimeDictionary {
    BitArray bits;

    public PrimeDictionary(int n) {
        bits = new BitArray(n + 1);
        for (int i = 0; 2 * i + 3 <= n; i++) {
            bits.Set(i, CheckPrimality(2 * i + 3));
        }
    }

    public PrimeDictionary(IEnumerable<int> primes) {
        bits = new BitArray(primes.Max());
        foreach(var prime in primes.Where(p => p != 2)) {
            bits.Set((prime - 3) / 2, true);
        }
    }

    public bool IsPrime(int k) {
        if (k == 2) {
            return true;
        }
        if (k % 2 == 0) {
            return false;
        }
        return bits[(k - 3) / 2];
    }
}

Natürlich müssen Sie die Definition von angeben CheckPrimality.


0

Ich denke, eine der schnellsten ist meine Methode, die ich gemacht habe.

void prime(long long int number) {
    // Establishing Variables
    long long int i = 5;
    int w = 2;
    const long long int lim = sqrt(number);

    // Gets 2 and 3 out of the way
    if (number == 1) { cout << number << " is hard to classify. \n";  return; }
    if (number == 2) { cout << number << " is Prime. \n";  return; }
    if (number == 3) { cout << number << " is Prime. \n";  return; }

    // Tests Odd Ball Factors
    if (number % 2 == 0) { cout << number << " is not Prime. \n";  return; }
    if (number % 3 == 0) { cout << number << " is not Prime. \n";  return; }

    while (i <= lim) {
        if (number % i == 0) { cout << number << " is not Prime. \n";  return; }
        // Tests Number
        i = i + w; // Increments number
        w = 6 - i; // We already tested 2 and 3
        // So this removes testing multepules of this
    }
    cout << number << " is Prime. \n"; return;
}

1
ein Fehler kann sein ... 6 - ich?
Hmmm

0

Ähnliche Idee wie der erwähnte AKS-Algorithmus

public static boolean isPrime(int n) {

    if(n == 2 || n == 3) return true;
    if((n & 1 ) == 0 || n % 3 == 0) return false;
    int limit = (int)Math.sqrt(n) + 1;
    for(int i = 5, w = 2; i <= limit; i += w, w = 6 - w) {
        if(n % i == 0) return false;
        numChecks++;
    }
    return true;
}

1
Keine Beziehung zum AKS-Algorithmus .
Graubart

In der for-Schleife müssen Sie nicht "i <= limit" aktivieren, es reicht aus, "i <limit" zu überprüfen. In jeder Iteration machen Sie also einen Vergleich weniger.
Andrushenko Alexander

0

Um herauszufinden, ob die Zahl oder die Zahlen in einem Bereich Primzahlen sind / sind.

#!usr/bin/python3

def prime_check(*args):
    for arg in args:
        if arg > 1:     # prime numbers are greater than 1
            for i in range(2,arg):   # check for factors
                if(arg % i) == 0:
                    print(arg,"is not Prime")
                    print(i,"times",arg//i,"is",arg)
                    break
            else:
                print(arg,"is Prime")
                
            # if input number is less than
            # or equal to 1, it is not prime
        else:
            print(arg,"is not Prime")
    return
    
# Calling Now
prime_check(*list(range(101)))  # This will check all the numbers in range 0 to 100 
prime_check(#anynumber)         # Put any number while calling it will check.

Führen Sie diesen Code aus, er funktioniert sowohl für eine Liste als auch für eine bestimmte Nummer
Harsh Singh

0
myInp=int(input("Enter a number: "))
if myInp==1:
    print("The number {} is neither a prime not composite no".format(myInp))
elif myInp>1:
    for i in range(2,myInp//2+1):
        if myInp%i==0:
            print("The Number {} is not a prime no".format(myInp))
            print("Because",i,"times",myInp//i,"is",myInp)
            break
    else:
        print("The Number {} is a prime no".format(myInp))
else:
    print("Alas the no {} is a not a prime no".format(myInp))

1
Wenn Sie eine Antwort schreiben, auch wenn diese korrekt ist, schreiben Sie bitte ein wenig, was Sie tun und warum. Auf diese Weise können Personen, die Ihre Antwort lesen, leichter erfassen, was Sie gelöst haben. Danke dir!
Kim

1
Klar Kim, danke, dass du darauf hingewiesen hast. Dies ist mein erstes Programm in Stackoverflow. Von nun an werde ich entsprechende Kommentare und Erklärungen hinzufügen.
DKB

0
public static boolean isPrime(int number) {
 if(number < 2)
   return false;
 else if(number == 2 || number == 3)
        return true;
      else {
        for(int i=2;i<=number/2;i++)
           if(number%i == 0)
             return false;
           else if(i==number/2)
                return true;
      }
    return false;
}

0

Sie könnten so etwas versuchen.

def main():
    try:
        user_in = int(input("Enter a number to determine whether the number is prime or not: "))
    except ValueError:
        print()
        print("You must enter a number!")
        print()
        return
    list_range = list(range(2,user_in+1))
    divisor_list = []
    for number in list_range:
        if user_in%number==0:
            divisor_list.append(number)
    if len(divisor_list) < 2:
        print(user_in, "is a prime number!")
        return
    else:
        print(user_in, "is not a prime number!")
        return
main()

Dies ist eine schreckliche Lösung, um die Primheit zu testen. Sobald Sie einen Teiler gefunden haben, kennen Sie die Antwort, aber dieser Code findet alle Teiler und entscheidet dann! Und es ignoriert die Anforderung des OP nach einem booleschen Prädikat, da es immer zurückgibt None.
cdlane

@cdlane Ich weiß, dass dies keine boolesche Rückgabefunktion ist, ich bin noch ein Anfänger in Python und ich weiß, dass es nicht perfekt ist, danke für das Kommentieren trotzdem
Patrick Jane

0

Die meisten vorherigen Antworten sind korrekt, aber hier ist eine weitere Möglichkeit, um zu testen, ob eine Zahl eine Primzahl ist. Als Auffrischung sind Primzahlen ganze Zahlen größer als 1, deren einzige Faktoren 1 und sich selbst sind. ( Quelle )

Lösung:

Normalerweise können Sie eine Schleife erstellen und mit dem Testen Ihrer Nummer beginnen, um festzustellen, ob sie durch 1,2,3 teilbar ist ... bis zu der Nummer, die Sie testen ... usw. Um die Überprüfungszeit zu verkürzen, können Sie Ihre Nummer durch dividieren Die Hälfte des Wertes Ihrer Zahl, da eine Zahl nicht genau durch die Hälfte ihres Wertes teilbar sein kann. Wenn Sie beispielsweise 100 als Primzahl sehen möchten, können Sie bis zu 50 durchlaufen.

Aktueller Code :

def find_prime(number):
    if(number ==1):
        return False
    # we are dividiing and rounding and then adding the remainder to increment !
    # to cover not fully divisible value to go up forexample 23 becomes 11
    stop=number//2+number%2
    #loop through up to the half of the values
    for item in range(2,stop):
        if number%item==0:
           return False
        print(number)
    return True


if(find_prime(3)):
    print("it's a prime number !!")
else:
    print("it's not a prime")  

Sie müssen nur die Quadratwurzel der Zahl überprüfen, die etwas kleiner als die Hälfte der Zahl ist. ZB für n = 100 müssen Sie nur auf 10 prüfen, nicht auf 50. Warum? Bei genau der Quadratwurzel sind die beiden Faktoren gleich. Für jeden anderen Faktor ist einer kleiner als sqrt (n) und der andere größer. Wenn wir also bis zum Check-up bis einschließlich sqrt (n) noch keinen gesehen haben, werden wir keinen mehr finden.
DanaJ

0

Wir können Java-Streams verwenden, um dies in O (sqrt (n)) zu implementieren. Beachten Sie, dass noneMatch eine shortCircuiting-Methode ist, die den Vorgang stoppt, wenn dies für die Ermittlung des Ergebnisses nicht erforderlich ist:

Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println(n == 2 ? "Prime" : IntStream.rangeClosed(2, ((int)(Math.sqrt(n)) + 1)).noneMatch(a -> n % a == 0) ? "Prime" : "Not Prime");

0

Mit Hilfe von Java-8-Streams und Lambdas kann es in wenigen Zeilen folgendermaßen implementiert werden:

public static boolean isPrime(int candidate){
        int candidateRoot = (int) Math.sqrt( (double) candidate);
        return IntStream.range(2,candidateRoot)
                .boxed().noneMatch(x -> candidate % x == 0);
    }

Die Leistung sollte nahe bei O (sqrt (N)) liegen . Vielleicht findet es jemand nützlich.


"range" sollte durch "rangeClosed" ersetzt werden, um CandidateRoot einzuschließen. Auch der Fall eines Kandidaten <2 sollte behandelt werden.
Udalmik

Wie unterscheidet sich das von der vorherigen Antwort von alirezafnatica ?
Graubart

0

Hier ist meine Antwort:

def isprime(num):
    return num <= 3 or (num + 1) % 6 == 0 or (num - 1) % 6 == 0

Die Funktion gibt True zurück, wenn eine der folgenden Eigenschaften True ist. Diese Eigenschaften definieren mathematisch, was eine Primzahl ist.

  1. Die Zahl ist kleiner oder gleich 3
  2. Die Zahl + 1 ist durch 6 teilbar
  3. Die Zahl - 1 ist durch 6 teilbar

>>> isprime(25)kehrt zurück True. Sie überprüfen eine sehr einfache notwendige Bedingung (Teilbarkeit durch 2 oder 3), aber dies ist nicht ausreichend .
DanaJ

Schön, dass Sie mit dieser Eigenschaft übereinstimmen: Jede Primzahl größer als 3 hat die Form 6n + 1 oder 6n + 5, aber es gibt Zahlen (als 25), die die Form 6n + 1 oder 6n + 5 haben, aber sie sind nicht Prime
Luis Felipe

0

Wenn ich eine schnelle Überprüfung durchführen muss, schreibe ich diesen einfachen Code basierend auf der grundlegenden Unterteilung zwischen Zahlen, die niedriger als die Quadratwurzel der Eingabe sind.

def isprime(n):
    if n%2==0:
        return n==2
    else:
        cota = int(n**0.5)+1
        for ind in range(3,2,cota):
            if n%ind==0:
                print(ind)
                return False
        return True != n==1

isprime(22783)
  • Das letzte True != n==1ist, den Fall zu vermeiden n=1.

-4

Erste Regel einer Primzahl: Wenn durch 2 geteilt, entspricht dies einer ganzen Zahl oder einer ganzen Zahl. Nein, es ist keine Primzahl.

Die schnellste Methode, um eine Computersprache zu verwenden, ist die Typübereinstimmung mit Zeichenfolgen, nicht mit Mathematik. Passen Sie den Punkt in einem String Float an.

  • Teilen Sie es durch 2 ,,, n = n / 2
  • Konvertiere dies in einen String ,,, n = string (n)
  • wenn "." in n: {printf "Ja, ich bin Prime!"
    }}

2
Die "erste Regel einer Primzahl" lautet: Wenn eine ganze Zahl größer als eins sie teilt, ist sie keine Primzahl. Es reicht nicht aus, es mit nur 2 zu testen. Das Konvertieren einer Zahl in eine Zeichenfolge, um zu testen, ob es sich um eine ganze Zahl handelt, ist möglicherweise die langsamste Methode, die Sie vernünftigerweise finden könnten.
JJJ
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.