Geben Sie bei einer gegebenen Zahl n alle Primzahlen kleiner als n aus. Wenn die angegebene Zahl beispielsweise 10 ist, geben Sie 2, 3, 5, 7 aus.

Ein naiver Ansatz besteht darin, eine Schleife von 0 bis n-1 zu durchlaufen und jede Zahl auf Primzahl zu überprüfen. Ein besserer Ansatz ist die Verwendung von Simple Sieve of Eratosthenes .

C

// This functions finds all primes smaller than 'limit'
// using simple sieve of eratosthenes.
void simpleSieve(int limit)
{
    // Create a boolean array "mark[0..limit-1]" and
    // initialize all entries of it as true. A value
    // in mark[p] will finally be false if 'p' is Not
    // a prime, else true.
    bool mark[limit];
    for(int i = 0; i<limit; i++) {
      mark[i] = true;
    }
  
    // One by one traverse all numbers so that their
    // multiples can be marked as composite.
    for (int p=2; p*p<limit; p++)
    {
        // If p is not changed, then it is a prime
        if (mark[p] == true)
        {
            // Update all multiples of p
            for (int i=p*p; i<limit; i+=p)
                mark[i] = false;
        }
    }
  
    // Print all prime numbers and store them in prime
    for (int p=2; p<limit; p++)
        if (mark[p] == true)
            cout << p << "  ";
}

Java

// This functions finds all primes smaller than 'limit'
// using simple sieve of eratosthenes.
static void simpleSieve(int limit)
{
   
    // Create a boolean array "mark[0..limit-1]" and
    // initialize all entries of it as true. A value
    // in mark[p] will finally be false if 'p' is Not
    // a prime, else true.
    boolean []mark = new boolean[limit];
    Arrays.fill(mark, true);
  
    // One by one traverse all numbers so that their
    // multiples can be marked as composite.
    for (int p = 2; p * p < limit; p++)
    {
        // If p is not changed, then it is a prime
        if (mark[p] == true)
        {
            // Update all multiples of p
            for (int i = p * p; i < limit; i += p)
                mark[i] = false;
        }
    }
  
    // Print all prime numbers and store them in prime
    for (int p = 2; p < limit; p++)
        if (mark[p] == true)
            System.out.print(p + " ");
}
 
// This code is contributed by rutvik_56.

Python3

# This functions finds all primes smaller than 'limit'
# using simple sieve of eratosthenes.
def simpleSieve(limit):
 
    # Create a boolean array "mark[0..limit-1]" and
    # initialize all entries of it as true. A value
    # in mark[p] will finally be false if 'p' is Not
    # a prime, else true.
    mark = [True for i in range(limit)]
 
    # One by one traverse all numbers so that their
    # multiples can be marked as composite.
    for p in range(p * p, limit - 1, 1):
 
        # If p is not changed, then it is a prime
        if (mark[p] == True):
 
            # Update all multiples of p
            for i in range(p * p, limit - 1, p):
                mark[i] = False
 
    # Print all prime numbers and store them in prime
    for p in range(2, limit - 1, 1):
        if (mark[p] == True):
            print(p, end=" ")
 
# This code is contributed by Dharanendra L V.

C#

// This functions finds all primes smaller than 'limit'
// using simple sieve of eratosthenes.
static void simpleSieve(int limit)
{
   
    // Create a boolean array "mark[0..limit-1]" and
    // initialize all entries of it as true. A value
    // in mark[p] will finally be false if 'p' is Not
    // a prime, else true.
    bool []mark = new bool[limit];
    Array.Fill(mark, true);
  
    // One by one traverse all numbers so that their
    // multiples can be marked as composite.
    for (int p = 2; p * p < limit; p++)
    {
       
        // If p is not changed, then it is a prime
        if (mark[p] == true)
        {
           
            // Update all multiples of p
            for (int i = p * p; i < limit; i += p)
                mark[i] = false;
        }
    }
  
    // Print all prime numbers and store them in prime
    for (int p = 2; p < limit; p++)
        if (mark[p] == true)
            Console.Write(p + " ");
}
 
// This code is contributed by pratham76.

Javascript

<script>
 
// This functions finds all primes smaller than 'limit'
// using simple sieve of eratosthenes.
function simpleSieve(limit)
{
   
    // Create a boolean array "mark[0..limit-1]" and
    // initialize all entries of it as true. A value
    // in mark[p] will finally be false if 'p' is Not
    // a prime, else true.
    var mark = Array(limit).fill(true);
 
  
    // One by one traverse all numbers so that their
    // multiples can be marked as composite.
    for (p = 2; p * p < limit; p++)
    {
        // If p is not changed, then it is a prime
        if (mark[p] == true)
        {
            // Update all multiples of p
            for (i = p * p; i < limit; i += p)
                mark[i] = false;
        }
    }
  
    // Print all prime numbers and store them in prime
    for (p = 2; p < limit; p++)
        if (mark[p] == true)
            document.write(p + " ");
}
 
// This code is contributed by todaysgaurav
 
</script>

Probleme mit Simple Sieve:
Das Sieb von Eratosthenes sieht gut aus, aber bedenken Sie die Situation, wenn n groß ist, das Simple Sieve steht vor den folgenden Problemen.

  • Ein Array der Größe Θ(n) passt möglicherweise nicht in den Speicher
  • Das einfache Sieb ist auch für etwas größere n nicht cachefreundlich. Der Algorithmus durchläuft das Array ohne Bezugsort

Segmentiertes Sieb
Die Idee eines segmentierten Siebs besteht darin, den Bereich [0..n-1] in verschiedene Segmente zu unterteilen und in allen Segmenten nacheinander Primzahlen zu berechnen. Dieser Algorithmus verwendet zuerst Simple Sieve, um Primzahlen zu finden, die kleiner oder gleich √(n) sind. Unten sind die Schritte aufgeführt, die beim segmentierten Sieb verwendet werden.

  1. Verwenden Sie Simple Sieve, um alle Primzahlen bis zur Quadratwurzel von 'n' zu finden, und speichern Sie diese Primzahlen in einem Array „prime[]“. Speichern Sie die gefundenen Primzahlen in einem Array 'prime[]'.
  2. Wir brauchen alle Primzahlen im Bereich [0..n-1]. Wir unterteilen diesen Bereich in verschiedene Segmente, sodass die Größe jedes Segments höchstens √n beträgt
  3. Tun Sie Folgendes für jedes Segment [low..high] 
    • Erstellen Sie eine Array-Markierung [high-low+1]. Hier benötigen wir nur O(x) Raum, wobei x eine Anzahl von Elementen in einem gegebenen Bereich ist.
    • Iteriere durch alle in Schritt 1 gefundenen Primzahlen. Markiere für jede Primzahl ihre Vielfachen im gegebenen Bereich [low..high].

In Simple Sieve benötigten wir O(n)-Platz, was für große n möglicherweise nicht machbar ist. Hier benötigen wir O(√n)-Raum und verarbeiten kleinere Bereiche gleichzeitig (Referenzort)

Unten ist die Implementierung der obigen Idee.

C++

// C++ program to print print all primes smaller than
// n using segmented sieve
#include <bits/stdc++.h>
using namespace std;
 
// This functions finds all primes smaller than 'limit'
// using simple sieve of eratosthenes. It also stores
// found primes in vector prime[]
void simpleSieve(int limit, vector<int> &prime)
{
    // Create a boolean array "mark[0..n-1]" and initialize
    // all entries of it as true. A value in mark[p] will
    // finally be false if 'p' is Not a prime, else true.
    vector<bool> mark(limit + 1, true);
 
    for (int p=2; p*p<limit; p++)
    {
        // If p is not changed, then it is a prime
        if (mark[p] == true)
        {
            // Update all multiples of p
            for (int i=p*p; i<limit; i+=p)
                mark[i] = false;
        }
    }
 
    // Print all prime numbers and store them in prime
    for (int p=2; p<limit; p++)
    {
        if (mark[p] == true)
        {
            prime.push_back(p);
            cout << p << " ";
        }
    }
}
 
// Prints all prime numbers smaller than 'n'
void segmentedSieve(int n)
{
    // Compute all primes smaller than or equal
    // to square root of n using simple sieve
    int limit = floor(sqrt(n))+1;
    vector<int> prime;
    prime.reserve(limit);
    simpleSieve(limit, prime);
 
    // Divide the range [0..n-1] in different segments
    // We have chosen segment size as sqrt(n).
    int low = limit;
    int high = 2*limit;
 
    // While all segments of range [0..n-1] are not processed,
    // process one segment at a time
    while (low < n)
    {
        if (high >= n)
           high = n;
         
        // To mark primes in current range. A value in mark[i]
        // will finally be false if 'i-low' is Not a prime,
        // else true.
        bool mark[limit+1];
        memset(mark, true, sizeof(mark));
 
        // Use the found primes by simpleSieve() to find
        // primes in current range
        for (int i = 0; i < prime.size(); i++)
        {
            // Find the minimum number in [low..high] that is
            // a multiple of prime[i] (divisible by prime[i])
            // For example, if low is 31 and prime[i] is 3,
            // we start with 33.
            int loLim = floor(low/prime[i]) * prime[i];
            if (loLim < low)
                loLim += prime[i];
 
            /* Mark multiples of prime[i] in [low..high]:
                We are marking j - low for j, i.e. each number
                in range [low, high] is mapped to [0, high-low]
                so if range is [50, 100] marking 50 corresponds
                to marking 0, marking 51 corresponds to 1 and
                so on. In this way we need to allocate space only
                for range */
            for (int j=loLim; j<high; j+=prime[i])
                mark[j-low] = false;
        }
 
        // Numbers which are not marked as false are prime
        for (int i = low; i<high; i++)
            if (mark[i - low] == true)
                cout << i << " ";
 
        // Update low and high for next segment
        low = low + limit;
        high = high + limit;
    }
}
 
// Driver program to test above function
int main()
{
    int n = 100000;
    cout << "Primes smaller than " << n << ":n";
    segmentedSieve(n);
    return 0;
}

Java

// Java program to print print all primes smaller than
// n using segmented sieve
 
 
import java.util.Vector;
import static java.lang.Math.sqrt;
import static java.lang.Math.floor;
 
class Test
{
    // This methid finds all primes smaller than 'limit'
    // using simple sieve of eratosthenes. It also stores
    // found primes in vector prime[]
    static void simpleSieve(int limit, Vector<Integer> prime)
    {
        // Create a boolean array "mark[0..n-1]" and initialize
        // all entries of it as true. A value in mark[p] will
        // finally be false if 'p' is Not a prime, else true.
        boolean mark[] = new boolean[limit+1];
         
        for (int i = 0; i < mark.length; i++)
            mark[i] = true;
      
        for (int p=2; p*p<limit; p++)
        {
            // If p is not changed, then it is a prime
            if (mark[p] == true)
            {
                // Update all multiples of p
                for (int i=p*p; i<limit; i+=p)
                    mark[i] = false;
            }
        }
      
        // Print all prime numbers and store them in prime
        for (int p=2; p<limit; p++)
        {
            if (mark[p] == true)
            {
                prime.add(p);
                System.out.print(p + "  ");
            }
        }
    }
      
    // Prints all prime numbers smaller than 'n'
    static void segmentedSieve(int n)
    {
        // Compute all primes smaller than or equal
        // to square root of n using simple sieve
        int limit = (int) (floor(sqrt(n))+1);
        Vector<Integer> prime = new Vector<>(); 
        simpleSieve(limit, prime);
      
        // Divide the range [0..n-1] in different segments
        // We have chosen segment size as sqrt(n).
        int low  = limit;
        int high = 2*limit;
      
        // While all segments of range [0..n-1] are not processed,
        // process one segment at a time
        while (low < n)
        {
            if (high >= n)
                high = n;
 
            // To mark primes in current range. A value in mark[i]
            // will finally be false if 'i-low' is Not a prime,
            // else true.
            boolean mark[] = new boolean[limit+1];
             
            for (int i = 0; i < mark.length; i++)
                mark[i] = true;
      
            // Use the found primes by simpleSieve() to find
            // primes in current range
            for (int i = 0; i < prime.size(); i++)
            {
                // Find the minimum number in [low..high] that is
                // a multiple of prime.get(i) (divisible by prime.get(i))
                // For example, if low is 31 and prime.get(i) is 3,
                // we start with 33.
                int loLim = (int) (floor(low/prime.get(i)) * prime.get(i));
                if (loLim < low)
                    loLim += prime.get(i);
      
                /*  Mark multiples of prime.get(i) in [low..high]:
                    We are marking j - low for j, i.e. each number
                    in range [low, high] is mapped to [0, high-low]
                    so if range is [50, 100]  marking 50 corresponds
                    to marking 0, marking 51 corresponds to 1 and
                    so on. In this way we need to allocate space only
                    for range  */
                for (int j=loLim; j<high; j+=prime.get(i))
                    mark[j-low] = false;
            }
      
            // Numbers which are not marked as false are prime
            for (int i = low; i<high; i++)
                if (mark[i - low] == true)
                    System.out.print(i + "  ");
      
            // Update low and high for next segment
            low  = low + limit;
            high = high + limit;
        }
    }
     
    // Driver method
    public static void main(String args[])
    {
        int n = 100;
        System.out.println("Primes smaller than " + n + ":");
        segmentedSieve(n);
    }
}

Python3

# Python3 program to print all primes
# smaller than n, using segmented sieve
import math
prime = []
 
# This method finds all primes
# smaller than 'limit' using
# simple sieve of eratosthenes.
# It also stores found primes in list prime
def simpleSieve(limit):
     
    # Create a boolean list "mark[0..n-1]" and 
    # initialize all entries of it as True.
    # A value in mark[p] will finally be False
    # if 'p' is Not a prime, else True.
    mark = [True for i in range(limit + 1)]
    p = 2
    while (p * p <= limit):
         
        # If p is not changed, then it is a prime
        if (mark[p] == True):
             
            # Update all multiples of p
            for i in range(p * p, limit + 1, p):
                mark[i] = False 
        p += 1
         
    # Print all prime numbers
    # and store them in prime
    for p in range(2, limit):
        if mark[p]:
            prime.append(p)
            print(p,end = " ")
             
# Prints all prime numbers smaller than 'n'
def segmentedSieve(n):
     
    # Compute all primes smaller than or equal
    # to square root of n using simple sieve
    limit = int(math.floor(math.sqrt(n)) + 1)
    simpleSieve(limit)
     
    # Divide the range [0..n-1] in different segments
    # We have chosen segment size as sqrt(n).
    low = limit
    high = limit * 2
     
    # While all segments of range [0..n-1] are not processed,
    # process one segment at a time
    while low < n:
        if high >= n:
            high = n
             
        # To mark primes in current range. A value in mark[i]
        # will finally be False if 'i-low' is Not a prime,
        # else True.
        mark = [True for i in range(limit + 1)]
         
        # Use the found primes by simpleSieve()
        # to find primes in current range
        for i in range(len(prime)):
             
            # Find the minimum number in [low..high]
            # that is a multiple of prime[i]
            # (divisible by prime[i])
            # For example, if low is 31 and prime[i] is 3,
            # we start with 33.
            loLim = int(math.floor(low / prime[i]) *
                                         prime[i])
            if loLim < low:
                loLim += prime[i]
                 
            # Mark multiples of prime[i] in [low..high]:
            # We are marking j - low for j, i.e. each number
            # in range [low, high] is mapped to [0, high-low]
            # so if range is [50, 100] marking 50 corresponds
            # to marking 0, marking 51 corresponds to 1 and
            # so on. In this way we need to allocate space
            # only for range
            for j in range(loLim, high, prime[i]):
                mark[j - low] = False
                 
        # Numbers which are not marked as False are prime
        for i in range(low, high):
            if mark[i - low]:
                print(i, end = " ")
                 
        # Update low and high for next segment
        low = low + limit
        high = high + limit
 
# Driver Code
n = 100
print("Primes smaller than", n, ":")
segmentedSieve(100)
 
# This code is contributed by bhavyadeep

C#

// C# program to print print
// all primes smaller than
// n using segmented sieve
using System;
using System.Collections;
 
class GFG
{
    // This methid finds all primes
    // smaller than 'limit' using simple
    // sieve of eratosthenes. It also stores
    // found primes in vector prime[]
    static void simpleSieve(int limit,
                            ArrayList prime)
    {
        // Create a boolean array "mark[0..n-1]"
        // and initialize all entries of it as
        // true. A value in mark[p] will finally be
        // false if 'p' is Not a prime, else true.
        bool[] mark = new bool[limit + 1];
         
        for (int i = 0; i < mark.Length; i++)
            mark[i] = true;
     
        for (int p = 2; p * p < limit; p++)
        {
            // If p is not changed, then it is a prime
            if (mark[p] == true)
            {
                // Update all multiples of p
                for (int i = p * p; i < limit; i += p)
                    mark[i] = false;
            }
        }
     
        // Print all prime numbers and store them in prime
        for (int p = 2; p < limit; p++)
        {
            if (mark[p] == true)
            {
                prime.Add(p);
                Console.Write(p + " ");
            }
        }
    }
     
    // Prints all prime numbers smaller than 'n'
    static void segmentedSieve(int n)
    {
        // Compute all primes smaller than or equal
        // to square root of n using simple sieve
        int limit = (int) (Math.Floor(Math.Sqrt(n)) + 1);
        ArrayList prime = new ArrayList();
        simpleSieve(limit, prime);
     
        // Divide the range [0..n-1] in
        // different segments We have chosen
        // segment size as sqrt(n).
        int low = limit;
        int high = 2*limit;
     
        // While all segments of range
        // [0..n-1] are not processed,
        // process one segment at a time
        while (low < n)
        {
            if (high >= n)
                high = n;
 
            // To mark primes in current range.
            // A value in mark[i] will finally
            // be false if 'i-low' is Not a prime,
            // else true.
            bool[] mark = new bool[limit + 1];
             
            for (int i = 0; i < mark.Length; i++)
                mark[i] = true;
     
            // Use the found primes by
            // simpleSieve() to find
            // primes in current range
            for (int i = 0; i < prime.Count; i++)
            {
                // Find the minimum number in
                // [low..high] that is a multiple
                // of prime.get(i) (divisible by
                // prime.get(i)) For example,
                // if low is 31 and prime.get(i)
                //  is 3, we start with 33.
                int loLim = ((int)Math.Floor((double)(low /
                            (int)prime[i])) * (int)prime[i]);
                if (loLim < low)
                    loLim += (int)prime[i];
     
                /* Mark multiples of prime.get(i) in [low..high]:
                    We are marking j - low for j, i.e. each number
                    in range [low, high] is mapped to [0, high-low]
                    so if range is [50, 100] marking 50 corresponds
                    to marking 0, marking 51 corresponds to 1 and
                    so on. In this way we need to allocate space only
                    for range */
                for (int j = loLim; j < high; j += (int)prime[i])
                    mark[j-low] = false;
            }
     
            // Numbers which are not marked as false are prime
            for (int i = low; i < high; i++)
                if (mark[i - low] == true)
                    Console.Write(i + " ");
     
            // Update low and high for next segment
            low = low + limit;
            high = high + limit;
        }
    }
     
    // Driver code
    static void Main()
    {
        int n = 100;
        Console.WriteLine("Primes smaller than " + n + ":");
        segmentedSieve(n);
    }
}
 
// This code is contributed by mits

Ausgabe: 

Primes smaller than 100:
2 3 5 7 11 13 17 19 23 29 31 37 41
43 47 53 59 61 67 71 73 79 83 89 97  

Beachten Sie, dass die Zeitkomplexität (oder eine Anzahl von Operationen) von Segmented Sieve mit Simple Sieve identisch ist . Es hat Vorteile für große 'n', da es eine bessere Referenzlokalität hat, wodurch ein besseres Caching durch die CPU ermöglicht wird und auch weniger Speicherplatz benötigt wird.
Dieser Artikel wurde von Utkarsh Trivedi beigesteuert. Bitte schreiben Sie Kommentare, wenn Sie etwas Falsches finden oder weitere Informationen zu dem oben diskutierten Thema teilen möchten 

Falls Sie an Live-Kursen mit Experten teilnehmen möchten , beziehen Sie sich bitte auf DSA Live-Kurse für Berufstätige und Competitive Programming Live for Students .