Już w czasach starożytnych znano metodę opisaną przez greckiego uczonego Eratostenesa z Cyreny. Podszedł on do rozwiązania od drugiej strony.
W poprzednim rozdziale opisaliśmy znajdowanie liczb pierwszych na podstawie ich definicji, tj. sprawdzając podzielność przez liczby mniejsze. Sposób ten nie jest najefektywniejszą metodą wyszukiwania liczb pierwszych - musimy wykonywać określoną ilość czasochłonnych dzieleń, tym większą, im większą wartość ma badana liczba.
W czasach starożytnych znano lepszą metodę opisaną przez greckiego uczonego Eratostenesa z Cyreny. Podszedł on do rozwiązania od drugiej strony - zamiast sprawdzać podzielność kolejnych liczb naturalnych przez znalezione liczby pierwsze, zaproponował wyrzucanie ze zbioru liczb naturalnych wielokrotności kolejnych liczb, które nie zostały wcześniej wyrzucone. To, co zostanie, będzie zbiorem liczb pierwszych, które nie posiadają innych podzielników jak 1 i same siebie. Metoda ta została nazwana sitem Eratostenesa i jest najszybszą metodą wyszukiwania liczb pierwszych w ograniczonym zbiorze.
Zobaczmy jak działa sito Eratostenesa. Spróbujmy wg tej metody odszukać wszystkie liczby pierwsze w zbiorze 20 początkowych liczb naturalnych.
Generacja liczb pierwszych przy pomocy sita Eratostenesa { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 }
Oto początkowy zbiór liczb. Najpierw usuniemy z niego liczbę 1 - nie jest to liczba pierwsza, ponieważ nie posiada dokładnie dwóch różnych podzielników.
{ 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 }
Bierzemy pierwszą liczbę 2 i usuwamy ze zbioru wszystkie jej wielokrotności. W ten sposób pozbyliśmy się liczb parzystych. Zauważ iż obliczanie wielokrotności nie wymaga mnożenia - wystarczy dodawać daną liczbę.
{ 2 3 5 7 9 11 13 15 17 19 }
Następną wolną liczbą jest 3. Usuwamy ze zbioru wszystkie wielokrotności liczby 3. Pozostaną więc liczby niepodzielne przez 2 i przez 3.
{ 2 3 5 7 11 13 17 19 }
Wykonane - w zbiorze pozostały same liczby pierwsze.
Przed opisem algorytmu musimy zdecydować, w jaki sposób będziemy reprezentować w pamięci komputera zbiór liczb. Najprostszym rozwiązaniem wydaje się być tablica wartości logicznych. Liczbę określa indeks elementu tablicy. Wartość elementu określa z kolei, czy dana liczba jest w zbiorze czy też jej tam nie ma. Na przykład:
t[5] - element ten odnosi się do liczby 5.
t[5] = true - liczba 5 jest w zbiorze.
t[5] = false - liczba 5 została ze zbioru wyrzucona.
Na początku wpiszemy do każdego elementu wartość true - wszystkie liczby będą w zbiorze. Następnie w elementach, których indeks jest równy wartości wyrzucanych liczb, umieścimy false. Na koniec przeglądniemy całą tablicę i wypiszemy te indeksy, dla których wskazywane elementy zawierają wciąż wartość true.
Dane wejściowe
g - górny kres przedziału, w którym poszukujemy liczb pierwszych, g N Dane wyjściowe
Kolejne liczby pierwsze zawarte w przedziale od 2 do g.
Zmienne pomocnicze
i - służy do sterowania pętlami iteracyjnymi, i N t[ ] - tablica logiczna odwzorowująca zbiór liczbowy. Indeksy elementów przebiegają wartości od 2 do g w - służy do tworzenia kolejnych wielokrotności, w N
krok 1: Czytaj g krok 2: Dla i = 2,3,...,g wykonuj t[i] true krok 3: Dla i = 2,3,...,g wykonuj kroki 4...7 krok 4: w 2i krok 5: Dopóki w g wykonuj kroki 6,7. Inaczej wykonaj następny obieg pętli z kroku 3. krok 6: t[w] false krok 7: w w + i krok 8: Dla i = 2,3,...,g jeżeli t[i] = true, to pisz i krok 9: Zakończ algorytm
Prezentowany algorytm Sita Eratostenesa jest maksymalnie uproszczony. Na początku odczytujemy górny kres przedziału, w którym będziemy wyznaczać liczby pierwsze umieszczając go w zmiennej g.
Następnie wykonywane są kolejno trzy pętle iteracyjne:
Pętla nr 1: - inicjalizacja
ustawia wszystkie elementy tablicy t[ ] na true. Zwróć uwagę, iż tablica jest ustawiana od elementu o indeksie 2. Zgodnie z tym, co powiedzieliśmy wyżej, tablica t[ ] odzwierciedla zbiór liczb naturalnych, w którym wartościami kolejnych liczb są indeksy elementów, natomiast zawartość tych elementów określa, czy reprezentowane przez nie liczby są (true) lub nie są (false) obecne w zbiorze.Pętla nr 2: - eliminacja
usuwa ze zbioru wszystkie wielokrotności kolejnych liczb. Dokonujemy tego bez żadnych sprawdzeń, co oczywiście nie jest zbytnio efektywne, ale za to bardzo proste. W zmiennej w tworzymy pierwszą wielokrotność i-tej liczby. Następnie wszystkie elementy o indeksach równych kolejnym wielokrotnościom ustawiamy na false. Po zakończeniu pętli 2 w tablicy t[ ] wartość true pozostaje jedynie w elementach, których indeksy są liczbami pierwszymi.Pętla nr 3: - prezentacja
przegląda kolejne elementy tablicy t[ ] i jeśli mają one wartość true, wyświetla ich indeks. Po wykonaniu tej pętli w oknie konsoli otrzymamy wszystkie liczby pierwsze zawarte w przedziale od 2 do g.
Wydruk z uruchomionego programu |
---|
Wyszukiwanie liczb pierwszych sitem Eratostenesa |
Microsoft Visual Basic 2005 Express Edition |
Poniższe, przykładowe programy są praktyczną realizacją omawianego w tym rozdziale algorytmu. Zapewne można je napisać bardziej efektywnie. To już twoje zadanie. Dokładny opis stosowanych środowisk programowania znajdziesz we wstępie. Programy przed opublikowaniem w serwisie edukacyjnym zostały dokładnie przetestowane. Jeśli jednak znajdziesz jakąś usterkę (co zawsze może się zdarzyć), to prześlij o niej informację do autora. Pozwoli to ulepszyć nasze artykuły. Będziemy Ci za to wdzięczni. | |||
W algorytmie wyszukiwania liczb pierwszych metodą Sita Eratostenesa nie występuje nigdzie potrzeba dzielenia. Wyznaczając wielokrotności wykonujemy jedynie proste dodawanie, które komputer realizuje bardzo szybko. Z tego powodu prezentowany algorytm czasowo jest najszybszym algorytmem rozwiązującym zadanie wyszukiwania liczb pierwszych.
Dla celów badawczych przyjmijmy za operację dominującą wyrzucanie ze zbioru wielokrotności kolejnych liczb. Operacja taka składa się z wyznaczenia wartości tej wielokrotności oraz wstawienia do elementu tablicy (o indeksie równym wielokrotności) wartości logicznej false. W tym celu program należy wyposażyć w odpowiedni licznik. Wykonanie tego zadania, z uwagi na jego prostotę, pozostawiam ambitnym czytelnikom. W poniższej tablicy zebraliśmy rezultaty pracy takiego programu.
Wyniki badania ilości wykonanych operacji wyrzucania liczb | ||
---|---|---|
Zakres poszukiwania liczb pierwszych | Ilość operacji wyrzucania | Wzrost |
2...10 | 8 | - |
2...100 | 283 | 35,375 |
2...1000 | 5070 | 17,915 |
2...10000 | 73669 | 14,530 |
2...100000 | 966751 | 13,123 |
2...1000000 | 11970035 | 12,382 |
2...10000000 | 142725365 | 11,924 |
2...100000000 | 1657511569 | 11,613 |
W pierwszej kolumnie mamy przeszukiwany przez algorytm zakres liczb naturalnych. Zakres przyrasta 10 razy.
Druga kolumna zawiera ilość operacji wyrzucania liczby ze zbioru, którą wykonał algorytm Sita Eratostenesa.
W trzeciej kolumnie liczymy wzrost operacji wyrzucania przy rozszerzeniu zakresu poszukiwań. Wzrost ten jest liczony jako iloraz liczby operacji z bieżącego wiersza przez liczbę operacji z wiersza poprzedniego.
Na podstawie danych zebranych w tej tabelce postaraj się odpowiedzieć na następujące pytania:
- Do jakiej liczby zmierza wzrost ilości operacji wyrzucania przy 10 krotnym wzroście zakresu poszukiwań liczb pierwszych?
- Jaką klasę czasowej złożoności obliczeniowej posiada ten algorytm?
- Uzasadnij swój wybór klasy złożoności obliczeniowej na podstawie analizy działania algorytmu.
- Dlaczego przyrost stabilizuje się dopiero dla dużych zakresów?
- Jaki wniosek można wysunąć na temat statystycznego rozkładu częstości występowania liczb pierwszych?
GNU Free Documentation License.
Źródło: mgr Jerzy Wałaszek