Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (2024)

Algorithmensammlung: Zahlentheorie

  • Euklidischer Algorithmus
  • Sieb des Eratosthenes
  • Primfaktorisierung
  • Fibonacci-Folge
  • Quadratwurzel mit Rest
  • Goldener Schnitt
  • Signum

Sieb des Eratosthenes[Bearbeiten]

Die Spezifikation des Algorithmus in Pseudocode ist in der Wikipedia zu finden.

Prinzip[Bearbeiten]

Das Sieb des Eratosthenes ist ein Verfahren, um alle natürlichen Zahlen (ferner nur mit „Zahlen“ bezeichnet) bis zu einer vorgegebenen Zahl n, einschließlich n selbst, auf Primalität zu testen (zu Primzahlen siehe auch die Seite Primfaktorisierung) und, sofern sie prim sind, auszugeben.Das Sieb des Eratosthenes "zäumt das Pferd von hinten auf": Es werden alle Zahlen bis n (inklusive) größer als 1 hintereinander aufgeschrieben. Dann werden die Zahlen der Reihe nach durchgegangen. Die echten Vielfachen der aktuellen Zahl (für 3 z. B. 6, 9, 12, ...) werden durchgestrichen. Übrig bleiben die Zahlen Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (1), die keine echten Vielfachen einer Zahl echt zwischen 1 und Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (2) sind. Dies sind sämtliche Primzahlen bis zur vorgegebenen Grenze.

Beispiel[Bearbeiten]

Sei Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (3). Hintereinander werden die Zahlen 2, 3, 4, 5, 6, 7, 8, 9, 10 aufgeschrieben. Die 2 wird betrachtet und ihre echten Vielfachen weggestrichen: 2, 3, 4, 5, 6, 7, 8, 9, 10. Dasselbe für die 3: 2, 3, 4, 5, 6, 7, 8, 9, 10. Übrig sind noch 2, 3, 5 und 7. Dies sind, wie wir überprüfen können, alle Primzahlen im betrachteten Intervall, sodass hier abgebrochen werden kann. Schritte, um das Verfahren zu optimieren, damit der Algorithmus wirklich schon so früh endet, werden im nächsten Absatz besprochen.

Optimierungen eines simplen Durchgehens aller Zahlen und ihrer echten Vielfachen[Bearbeiten]

Es müssen nur die Zahlen bis einschließlich Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (4) betrachtet werden, wobei Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (5) den ganzzahligen Anteil (die Abrundungsfunktion) symbolisiert. Denn sei Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (6), dann gilt für die Vielfachen: Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (7), alle Vielfachen von Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (8) wurden also bereits als Vielfache von Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (9)gestrichen.

Bereits gestrichene Zahlen müssen nicht mehr betrachtet werden, da ihre echten Vielfachen garantiert durch einen echten Teiler der gestrichenen Zahl teilbar sind.

Weiter optimieren kann man unter anderem, indem man das Wegstreichen der echten Vielfachen einer Zahl Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (10) erst bei Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (11) beginnt. Denn alle Vielfachen Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (12) sind von der Form Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (13) mit Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (14). Damit wurden sie aber als ganzzahlige Vielfachen einer kleineren Zahl schon überprüft.

Komplexitätstheoretische Beschreibung[Bearbeiten]

Durch diese und weitere Optimierungen lässt sich die Laufzeit auf Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (15) reduzieren. Beim Vergleich verschiedener Implementierungen und Varianten des Algorithmus ist die Ordnung der Laufzeit aber nur bedingt von Nutzen, da sie Konstanten außer Acht lässt. Bei diesem speziellen Problem wird der Sachverhalt bei einem Vergleich verschiedener Varianten auch bei großen n offensichtlich.

Die Speicherplatzkomplexität lässt sich auf Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (16) drücken.

Implementierungen[Bearbeiten]

Haskell[Bearbeiten]

Ein einfaches Primzahlsieb in der Programmiersprache Haskell implementiert. Der Speicherbedarf des Algorithmus ist in Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (17) Bits, wobei Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (18) die Anzahl der auszugebenen Primzahlen und Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (19) die größte auszugebene Primzahl bezeichnet.

> module Sieve> where > sieb :: [Int] -> [Int]> sieb (l:ls) = l:sieb[x | x <- ls, mod x l /= 0]> take_primes n = take n $ sieb [2..]

Ausführen via

# hugs Sieveoder für eine schnellere Version# ghc -O2 --make Sieve.lhs# ghci Sieve

Im Haskell-Interpeter zur Ausgabe der beispielsweise ersten 100 Primzahlen:

Prelude Sieve> take_primes 100

C#[Bearbeiten]

Folgende eigenständig lauffähige Konsolenanwendung (.NET 2.0) gibt alle Primzahlen bis n nach dem Sieb des Eratosthenes aus:

using System;using System.Collections.Generic;using System.Text;namespace eratosthenes{ class Program { static void Main(string[] args) { int n = 100; bool[] prime = new bool[n]; //Zuerst alle Zahlen von 2 bis n als Primzahl markieren for (int i = 2; i < n; i++) { prime[i] = true; } //Einzelner Abschnitt { //Wir wollen bei 2 anfangen int i = 2; //Alle Produkte des Teilers i //angefangen bei 2, bis kleiner n durchlaufen //Wenn n = 50, dann ist bei i = 7 Schluss, weil das Produkt = 49 ist for (; i * i < n; i++) { //Wenn die Zahl im Array als Primzahl markiert ist //Was bei den ersten beiden 2 und 3 definitiv der Fall ist if (prime[i]) { //Primzahl bis Wurzel(n) ausgeben Console.WriteLine(i); //Alle weiteren Produkte des Teilers i //angefangen beim Produkt i * i bis kleiner n durchlaufen //j wird mit i beim nächsten Durchlauf (Vielfaches) addiert for (int j = i * i; j < n; j += i) { //Dies kann unmöglich eine Primzahl sein //weil es ein Vielfaches von i ist. prime[j] = false; } } } //Alle Primzahlen ausgeben for (; i < n; i++) { if (prime[i]) { Console.WriteLine(i); } } }  Console.ReadLine(); } }}

Delphi[Bearbeiten]

Folgende Konsolenanwendung gibt mit Hilfe der Funktion isPrim() von einer bestimmten Zahlenmenge die Primzahlen aus.

program Primzahl;{$APPTYPE CONSOLE}uses SysUtils;function IsPrim(AInteger: Integer): boolean;var i: Integer;begin result := true; if (AInteger <= 1) then //Wenn Zahl kleiner ist als 2: keine Primzahl begin result := false; exit; //Funktion beenden end; for i := 2 to Round(Sqrt(AInteger)) do //Wenn eine Zahl n von 2 bis Wurzel(n) begin // nicht teilbar ist, ist sie eine Primzahl if AInteger mod i = 0 then //mod: Modulo = Rest begin result := false; exit; end; end;end;var a, b: Integer; i: Integer;begin Write('von: '); Readln(a); //a abfragen Write('bis: '); Readln(b); //b abfragen for i := a to b do if IsPrim (i) then Writeln(i); //wenn i eine Primzahl ist: i ausgeben Readln;end.

Python[Bearbeiten]

Dieses Script bittet den Benutzer zuerst nach einer Obergrenze und gibt danach alle Primzahlen bis zu dieser Grenze aus.

#!/usr/bin/env python# -*- coding: utf-8 -*-def main(): # Frage den Benutzer nach einer Obergrenze bis zu der gesucht werden soll while True: try: obergrenze = int(raw_input('Bitte geben Sie eine Obergrenze ein: ')) break except ValueError: print 'Dies ist keine gültige Obergrenze. Bitte verwenden Sie eine Ganzzahl!' # Jede Zahl zwischen 1 und obergrenze wird zuerst als prim angenommen zahlen = [True]*(obergrenze+1) # Da 0 und 1 keine Primzahlen sind, werden sie auf False gesetzt zahlen[0] = False zahlen[1] = False i = 2 while i*i <= obergrenze: if zahlen[i]: # Die Zahl i ist als prim markiert # Streiche alle Vielfachen von i for k in range(i*i,obergrenze+1,i): zahlen[k] = False i = i+1 # Ausgabe aller gefundenen Zahlen for i, v in enumerate(zahlen): if v: print i, 'ist prim.' return 0if __name__ == '__main__': main()

Oder mit set für die zusammengesetzten Zahlen:

#!/usr/bin/env python# -*- coding: utf-8 -*-# Python 3# Frage den Benutzer nach einer Obergrenze bis zu der gesucht werden sollwhile True: try: obergrenze = int(input('Bitte geben Sie eine Obergrenze ein: ')) break except ValueError: print ('Dies ist keine gültige Obergrenze. Bitte verwenden Sie eine Ganzzahl!')print (2)noprime = set()for n in range (3, obergrenze+1, 2): if n not in noprime: print (n) # alle ungeraden Vielfachen von n von n*n bis Obergrenze in ein set aufnehmen: for i in range(n*n, obergrenze+1, 2*n): noprime.add(i) else: noprime.discard(n) # wird nicht mehr gebraucht; dieser Schritt kann auch weggelassen werden

C++[Bearbeiten]

Das Programm fragt zunächst nach einer Obergrenze und gibt dann alle Primzahlen bis zu dieser aus.

#include<iostream>#include<cmath>using namespace std; int main(void){ unsigned limit;  cout << "Please insert upper limit.\n"; cin >> limit;  bool *Stroke = new bool[limit+1]; Stroke[0]=1; Stroke[1]=1; for(unsigned i=2; i<=limit; ++i) Stroke[i] = 0;  unsigned prime=2; while(pow((double)prime,2.0)<=limit){ for(unsigned i = (int)pow((double)prime,2.0); i<=limit; i+=prime){ Stroke[i]=1; }  do ++prime; while(Stroke[prime]); }  cout << "\nPrimes less or equal " << limit << " are:\n"; for(unsigned i=0; i<=limit; ++i){ if(!Stroke[i]) cout << i << endl; } delete[] Stroke; return 0;}

Eine andere Variante, die neuere Sprachfeatures (Lambdas, automatische Typableitung - C++11) sowie Container und Algorithmen der Standard Template Library (STL) benutzt, ist die nachfolgende. Dabei wird das Erase-Remove-Idiom benutzt: Der STL-Algorithmus remove_if schiebt alle Elemente des std::vector-Containers, die das durch ein Lambda-Konstrukt ([p](auto q){ ... }) formulierte Teilbarkeits-Kriterium erfüllen, ans Ende des Containers und gibt einen Iterator, der auf den Anfang des zu löschenden Bereiches zeigt, zurück. Mit candidates.erase(..., end(candidates)) schließlich wird der gesamte Bereich gelöscht (was intern lediglich eine Änderung der Längen-Variablen des Containers bedeutet).

#include <iostream>#include <iterator>#include <vector>#include <algorithm>#include <numeric>using namespace std;vector<unsigned> primes_upto(unsigned limit){ vector<unsigned> candidates(limit - 1); iota(begin(candidates), end(candidates), 2); // candidates = 2, 3, ..., n auto const upper_limit = (limit + 1) / 2; // ceil(limit/2) for (auto candidate = begin(candidates); // vector<unsigned>::iterator *candidate <= upper_limit; ++candidate) { auto const p = *candidate;  // 'erase-remove idiom': // remove_if(...) moves all multiples of p to the end and returns // an iterator to the beginning of the (re)moved part; // candidates.erase(..., end(candidates)) actually deletes these values candidates.erase(remove_if(candidate + 1, // don't remove p itself end(candidates), [p](auto q){ // capture p by value return (q % p == 0); }), end(candidates)); } return candidates; // copy elision guaranteed by C++ standard}int main(){ unsigned limit;  cout << "Please insert upper limit.\n"; cin >> limit; auto primes = primes_upto(limit); for (auto p : primes) cout << p << " "; cout << endl;}

R[Bearbeiten]

Limit heißt die Obergrenze, bis zu der alle Primzahlen ausgegeben werden.

sieb<-function(limit){ (vek<-2:limit)[1==apply(0==outer(vek, vek, "%%"), 1, sum)] # Primzahlen bis limit # %% Division mit Rest oder modulo}

Go[Bearbeiten]

Hier ein möglicher Quelltext eines Go-Programms zur Ausgabe der Primzahlen von 1-1000 (Der Bereich kann natürlich beliebig erweitert werden). Die Primzahlen werden dann in der Console ausgegeben. Dieses Programm kann auf der offiziellen Golang-Seite ausprobiert werden. Die Erklärungen sind identisch mit denen vom Java-Quellcode.

package mainimport "math"func main () {var limit uint = 1000var zahl, zaehler uintvar primzahl boolfor zahl = 2; zahl <= limit; zahl++ {primzahl = truefor zaehler = 2; zaehler <= zahl/2; zaehler++ {if math.Mod(float64(zahl), float64(zaehler)) == 0 {primzahl = falsebreak}}if primzahl == true {println(zahl, " ist eine Primzahl")}}}
Algorithmensammlung: Zahlentheorie: Sieb des Eratosthenes – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher (2024)
Top Articles
Latest Posts
Article information

Author: Kieth Sipes

Last Updated:

Views: 5967

Rating: 4.7 / 5 (67 voted)

Reviews: 82% of readers found this page helpful

Author information

Name: Kieth Sipes

Birthday: 2001-04-14

Address: Suite 492 62479 Champlin Loop, South Catrice, MS 57271

Phone: +9663362133320

Job: District Sales Analyst

Hobby: Digital arts, Dance, Ghost hunting, Worldbuilding, Kayaking, Table tennis, 3D printing

Introduction: My name is Kieth Sipes, I am a zany, rich, courageous, powerful, faithful, jolly, excited person who loves writing and wants to share my knowledge and understanding with you.