Informatyka

Sito Eratostenesa: jak znaleźć liczby pierwsze algorytmem

Sito Eratostenesa krok po kroku: wykreślanie wielokrotności od kwadratu, przykład dla n = 30, kod w Pythonie, złożoność O(n log log n) i typowe błędy.

Ilustracja: tablica liczb od 2 do 30 z wykreślonymi wielokrotnościami i zakreślonymi liczbami pierwszymi
Obraz wygenerowany przez AI

Idea: eliminujemy liczby złożone

Zamiast sprawdzać każdą liczbę osobno, sito działa odwrotnie: usuwa liczby, o których wiadomo, że są złożone. Wielokrotność liczby pierwszej p (poza samą p) ma dzielnik p, więc pierwsza być nie może. Po usunięciu wielokrotności wszystkich odpowiednich liczb pierwszych zostają tylko liczby pierwsze. Pojęcie liczby pierwszej i inne metody jej sprawdzania opisuje artykuł o liczbach pierwszych; tu chodzi o wypisanie wszystkich takich liczb w przedziale.

Algorytm jest przypisywany Eratostenesowi z Cyreny. Dwie obserwacje czynią go szybkim:

  • Start od kwadratu. Wielokrotności p mniejsze niż p² mają mniejszy dzielnik pierwszy, więc zostały już wykreślone wcześniej. Wykreślanie zaczynasz zatem od p².
  • Koniec na pierwiastku. Gdy kwadrat kolejnej niewykreślonej liczby przekracza n, nie ma już czego wykreślać. Wystarczy więc obsłużyć liczby nie większe niż √n.

Przebieg krok po kroku dla n = 30

Zapisz liczby od 2 do 30. Pierwiastek z 30 to około 5,48, więc wykreślanie prowadzisz tylko dla 2, 3 i 5; następna niewykreślona liczba, czyli 7, ma kwadrat 49, większy od 30.

Przesuń tabelę, aby zobaczyć wszystkie kolumny →

KrokWybrana liczba pWykreślasz od p²Nowo wykreśloneZostaje liczb
0brakbrakbrak29 (od 2 do 30)
1244, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 3015
2399, 15, 21, 2711
35252510
4749 > 30, koniecbrak10

W kroku 2 liczby 12, 18, 24 i 30 są wielokrotnościami 3, ale zostały wykreślone już w kroku 1, więc w tabeli ich nie ma. W kroku 3 wielokrotność 30 także była już wykreślona. Po zakończeniu zostaje dziesięć liczb: 2, 3, 5, 7, 11, 13, 17, 19, 23 i 29. To wszystkie liczby pierwsze nie większe niż 30.

Stan tablicy po każdym kroku:

Przesuń tabelę, aby zobaczyć wszystkie kolumny →

Po krokuNiewykreślone liczby
1 (liczba 2)2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29
2 (liczba 3)2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 29
3 (liczba 5)2, 3, 5, 7, 11, 13, 17, 19, 23, 29

Pseudokod

wejście: n
tablica jest[0..n], na początku wszystkie wartości prawda
jest[0] i jest[1] ustaw na fałsz
dla p od 2 do pierwiastka z n:
    jeśli jest[p] jest prawdą:
        dla w od p*p do n, co p:
            jest[w] = fałsz
wynik: wszystkie indeksy i, dla których jest[i] jest prawdą

Tablica logiczna zastępuje wykreślanie na kartce: „prawda” oznacza, że liczba nadal może być pierwsza, a „fałsz”, że jest złożona albo nie jest brana pod uwagę (0 i 1).

Implementacja w Pythonie

import math

def sito(n):
    jest = [True] * (n + 1)
    jest[0:2] = [False, False]          # 0 i 1 nie są pierwsze
    for p in range(2, math.isqrt(n) + 1):
        if jest[p]:
            for w in range(p * p, n + 1, p):
                jest[w] = False
    return [i for i, x in enumerate(jest) if x]

print(sito(30))

Program uruchomiony w Pythonie 3.13 wypisuje:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

To ten sam wynik, który wyszedł z ręcznego przebiegu. Funkcja math.isqrt zwraca całkowitą część pierwiastka, więc pętla zewnętrzna kończy się na ostatniej liczbie, której kwadrat nie przekracza n. Uruchomienie tej samej funkcji dla większych wartości daje 25 liczb pierwszych do 100, 168 do 1000 i 78498 do miliona.

Złożoność w prostych słowach

Czas. Każdą liczbę wykreślasz niewiele razy: tyle, ile ma różnych dzielników pierwszych, i to tylko tych nie większych od √n. Sumarycznie daje to liczbę kroków rzędu n · log log n. Funkcja log log n rośnie bardzo wolno, więc w praktyce czas jest prawie proporcjonalny do n: dziesięć razy większy przedział to niewiele więcej niż dziesięć razy więcej pracy.

Pamięć. Algorytm potrzebuje tablicy o rozmiarze n, czyli pamięci rzędu n. To główne ograniczenie: dla bardzo dużych n tablica może nie mieścić się w pamięci, dlatego stosuje się warianty działające na kolejnych fragmentach przedziału.

Przesuń tabelę, aby zobaczyć wszystkie kolumny →

WielkośćZapisCo oznacza
CzasO(n log log n)prawie liniowo względem n
PamięćO(n)jedna wartość logiczna na liczbę

Dla porównania metoda dzielenia przez liczby pierwsze do √n sprawdza każdą liczbę osobno, więc przy szukaniu wszystkich liczb pierwszych w przedziale sito zwykle wypada lepiej. Przy sprawdzeniu jednej, dużej liczby sito jest zbędne, bo wystarczy test dzielników.

Typowe błędy

Przesuń tabelę, aby zobaczyć wszystkie kolumny →

BłądSkutekPoprawka
Wykreślanie od 2p zamiast od p²Poprawny wynik, ale więcej niepotrzebnej pracyZaczynaj od p * p
Zostawienie 0 i 1 jako „pierwszych”Zły wynikUstaw jest[0] i jest[1] na False
Zewnętrzna pętla do nPoprawny wynik, ale bez zysku z optymalizacjiPętla do math.isqrt(n)
Tablica o rozmiarze n zamiast n + 1Błąd indeksu lub pominięcie liczby nRozmiar n + 1
Wykreślanie wielokrotności liczby złożonejZbędne krokiSprawdź warunek if jest[p]

Zadania do samodzielnego rozwiązania

  1. Wykonaj ręcznie sito dla n = 50. Dla których liczb p wykreślasz wielokrotności? Odpowiedź: 2, 3, 5 i 7, bo 7² = 49 ≤ 50, a 11² = 121 > 50. Zostaje 15 liczb pierwszych, od 2 do 47.
  2. Dla n = 100 napisz, jaka jest ostatnia liczba p, dla której wykreślasz. Odpowiedź: 7, bo 11² = 121 > 100.
  3. Zmień kod tak, żeby zwracał liczbę liczb pierwszych nie większych niż n, i sprawdź ją dla n = 100. Odpowiedź: 25.

Zobacz też: Algorytm, NWW i NWD, System binarny.

Najczęstsze pytania (FAQ)

Co to jest sito Eratostenesa?

To algorytm wyznaczania wszystkich liczb pierwszych z przedziału od 2 do n przez eliminację liczb złożonych. Wykreślasz wielokrotności kolejnych liczb pierwszych, a niewykreślone liczby są pierwsze.

Dlaczego wykreślanie zaczyna się od kwadratu liczby?

Mniejsze wielokrotności p mają mniejszy dzielnik pierwszy, więc zostały już wykreślone we wcześniejszych krokach. Na przykład 6 = 2 · 3 jest usunięta przy liczbie 2, a przy 3 nowe liczby zaczynają się dopiero od 9.

Do jakiej liczby trzeba wykreślać?

Do największej liczby, której kwadrat nie przekracza n. Dla n = 30 to 5, dla n = 100 to 7.

Jaka jest złożoność sita Eratostenesa?

Czas działania wynosi O(n log log n), czyli jest prawie liniowy względem n, a pamięć O(n).

Czy sito nadaje się do sprawdzenia, czy jedna liczba jest pierwsza?

Nie jest to dobry wybór: tablica dla n liczb jest zbędna, gdy wystarczy sprawdzić dzielniki do pierwiastka. Sito opłaca się, gdy potrzebujesz wszystkich liczb pierwszych z przedziału.

Czy 1 jest liczbą pierwszą w sicie?

Nie. W kodzie jedynkę i zero od razu oznaczasz jako niepierwsze, bo liczba pierwsza ma dokładnie dwa różne dzielniki naturalne.

← Więcej: Informatyka