Crivello di Eratostene in Python & C++

⚡ Riepilogo intelligente

Il crivello di Eratostene è un algoritmo classico per la ricerca di numeri primi che filtra i numeri composti contrassegnando iterativamente i multipli di ciascun numero primo, lasciando solo i numeri primi entro un limite superiore prescelto per una ricerca rapida.

  • 🔢 Idea centrale: Contrassegna i multipli di ogni numero primo a partire da 2 per isolare i numeri primi fino a n.
  • 🧮 Loop Bound: Iterare solo fino alla radice quadrata di n perché i fattori più grandi sono già stati eliminati.
  • Complessità temporale: L'algoritmo ha una complessità temporale di O(n log log n), che è quasi lineare per intervalli pratici.
  • Setaccio segmentato: La suddivisione dell'intervallo in blocchi riduce la memoria ausiliaria da O(n) a O(√n).
  • 🧪 Casi d'uso: La crittografia, l'hashing, la programmazione competitiva e la teoria dei numeri si basano sulla generazione rapida di numeri primi.

Crivello di Eratostene in Python

Che cos'è il crivello di Eratostene?

Il crivello di Eratostene è il più semplice crivello per numeri primi. Si tratta di un algoritmo utilizzato per scoprire tutti i numeri primi entro un dato limite. Esistono diversi crivelli per numeri primi, tra cui il crivello di Eratostene, il crivello di Atkin e il crivello di Sundaram.

La parola "setaccio" si riferisce a un utensile che filtra le sostanze. Nello stesso spirito, l'algoritmo del setaccio in Python e in altri linguaggi si riferisce a un metodo che filtra i numeri primi da un elenco di numeri interi.

Questo algoritmo filtra i numeri primi utilizzando un approccio iterativo. Il processo di filtraggio inizia con il più piccolo numero primo. Un numero primo è un numero naturale maggiore di 1 che ha solo due divisori, ovvero 1 e il numero stesso. Numbers I numeri che non sono primi sono chiamati numeri composti.

Perché usare il crivello di Eratostene?

Nel metodo del crivello di Eratostene, si seleziona prima un piccolo numero primo e si filtrano tutti i suoi multipli. Il processo si ripete ciclicamente su un intervallo dato, producendo in modo efficiente tutti i numeri primi fino a n senza dover eseguire la divisione per tentativi su ciascun candidato.

Questo rende il crivello più veloce rispetto al controllo della primalità di un numero alla volta. È ampiamente utilizzato nella teoria dei numeri, nella crittografia, nell'hashing e nella programmazione competitiva, dove è necessario generare rapidamente molti numeri primi.

Per esempio:

Consideriamo l'intervallo numerico da 2 a 10.

Algoritmo del crivello di Eratostene

Dopo aver applicato il Crivello di Eratostene, si otterrà l'elenco dei numeri primi 2, 3, 5, 7.

Algoritmo del crivello di Eratostene

Algoritmo Setaccio di Eratostene

Ecco l'algoritmo per il Setaccio di Eratostene:

Passo 1) Crea un elenco di numeri da 2 all'intervallo n dato. Iniziamo con 2 perché è il più piccolo e il primo numero primo.

Passo 2) Seleziona il numero più piccolo nell'elenco, x (inizialmente x è uguale a 2), scorri l'elenco e filtra i numeri composti corrispondenti contrassegnando tutti i multipli del numero selezionato.

Passo 3) Quindi scegli il numero primo successivo o il numero non contrassegnato più piccolo nell'elenco e ripeti il ​​passaggio 2.

Passo 4) Ripeti il ​​passaggio precedente finché il valore di x non è minore o uguale alla radice quadrata di n (x<=Algoritmo Setaccio di Eratostene).

Nota: Il ragionamento matematico è piuttosto semplice. L'intervallo numerico n può essere fattorizzato come:

n = a * b

Ancora una volta, n = Algoritmo Setaccio di Eratostene * Algoritmo Setaccio di Eratostene

= (fattore minore di Algoritmo Setaccio di Eratostene) * (fattore maggiore di Algoritmo del crivello di Eratostene)

Quindi almeno uno dei fattori primari oppure entrambi devono essere <= Algoritmo Setaccio di Eratostene. Pertanto, attraversando fino a Algoritmo Setaccio di Eratostene sarà sufficiente.

Passo 5) Dopo questi quattro passaggi, i numeri rimanenti non contrassegnati saranno tutti i numeri primi nell'intervallo n dato.

Esempio lavorato

Esempio:

Facciamo un esempio e vediamo come funziona.

Per questo esempio, troveremo l'elenco dei numeri primi da 2 a 25. Quindi, n = 25.

Passo 1) Come primo passo, prenderemo un elenco di numeri da 2 a 25, dato che abbiamo scelto n = 25.

Algoritmo Setaccio di Eratostene

Passo 2) Quindi selezioniamo il numero più piccolo nell'elenco, x. Inizialmente x = 2 perché è il più piccolo numero primo. Poi scorriamo l'elenco e segniamo i multipli di 2.

I multipli di 2 per il valore di n dato sono: 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24.

Algoritmo del crivello di Eratostene

Nota: Il colore blu indica il numero selezionato, mentre il colore rosa indica i multipli eliminati.

Passo 3) Quindi scegliamo il successivo numero non contrassegnato più piccolo, che è 3, e ripetiamo l'ultimo passaggio contrassegnando i multipli di 3.

Algoritmo del crivello di Eratostene

Passo 4) Ripetiamo il passaggio 3 nello stesso modo finché x = Algoritmo del crivello di Eratostene o 5.

Algoritmo del crivello di Eratostene

Passo 5) I numeri rimanenti non contrassegnati sono i numeri primi da 2 a 25.

Algoritmo del crivello di Eratostene

Pseudo-Code

Il seguente pseudocodice illustra la struttura di base del Crivello di Eratostene prima di tradurla in codice vero e proprio.

Begin
	Declare a boolean array of size n and initialize it to true
	For all numbers i : from 2 to sqrt(n)
     		IF bool value of i is true THEN
         			i is prime
         			For all multiples of i (i<n)
             			mark multiples of i as composite
Print all unmarked numbers
End

Setaccio di Eratostene C/C++ Code Esempio

Di seguito è riportato un completo C++ Implementazione del Crivello di Eratostene che stampa ogni numero primo fino a un limite superiore scelto.

#include <iostream>
#include <cstring>
using namespace std;
void Sieve_Of_Eratosthenes(int n)
{
    // Create and initialize a boolean array
    bool primeNumber[n + 1];
    memset(primeNumber, true, sizeof(primeNumber));
    for (int j = 2; j * j <= n; j++) {
        if (primeNumber[j] == true) {
            // Update all multiples of i as false
            for (int k = j * j; k <= n; k += j)
                primeNumber[k] = false;
        }
    }
    for (int i = 2; i <= n; i++)
        if (primeNumber[i])
            cout << i << " ";
}
int main()
{
    int n = 25;
    Sieve_Of_Eratosthenes(n);
    return 0;
}

Produzione:

2 3 5 7 11 13 17 19 23

Setaccio di Eratostene Python Esempio di programma

Le seguenti Python Il programma implementa lo stesso algoritmo utilizzando una lista booleana e un ciclo while.

def SieveOfEratosthenes(n):
# Create a boolean array
	primeNumber = [True for i in range(n+2)]
	i = 2
	while (i * i <= n):
		if (primeNumber[i] == True):
			# Update all multiples of i as false
			for j in range(i * i, n+1, i):
				primeNumber[j] = False
		i += 1
	for i in range(2, n):
		if primeNumber[i]:
			print(i)
n = 25
SieveOfEratosthenes(n)

Produzione:

2
3
5
7
11
13
17
19
23

Setaccio segmentato

Abbiamo visto che il Crivello di Eratostene esegue un ciclo su tutto l'intervallo numerico. Pertanto, necessita di uno spazio di memoria O(n) per memorizzare i numeri. La situazione si complica quando si cerca di trovare i numeri primi in un intervallo molto ampio, perché non è fattibile allocare un blocco di memoria così grande per un n maggiore.

L'algoritmo può essere ottimizzato introducendo alcune nuove funzionalità. L'idea è di dividere l'intervallo numerico in segmenti più piccoli e calcolare i numeri primi in quei segmenti uno per uno. Questo è un modo efficiente per ridurre la complessità dello spazio. Questo metodo è chiamato setaccio segmentato.

L'ottimizzazione può essere ottenuta nel modo seguente:

  1. Usa un semplice setaccio per trovare i numeri primi da 2 a Setaccio segmentato e memorizzarli in un array.
  2. Dividere l'intervallo [0...n-1] in più segmenti di dimensione massima Setaccio segmentato.
  3. Per ogni segmento, scorri il segmento e contrassegna i multipli dei numeri primi trovati nel passaggio 1. Questo passaggio richiede O(Setaccio segmentato) al massimo.

Il crivello normale richiede O(n) spazio di memoria ausiliaria, mentre il crivello segmentato richiede O(Setaccio segmentato), il che rappresenta un miglioramento sostanziale per valori elevati di n. Il metodo presenta tuttavia anche uno svantaggio, in quanto non migliora la complessità temporale.

Analisi della complessità

Comprendere la complessità sia spaziale che temporale aiuta a scegliere tra il setaccio tradizionale e il setaccio segmentato in base alla dimensione del problema.

Complessità spaziale:

L'algoritmo del crivello di Eratostene semplice richiede uno spazio di memoria O(n). Il crivello segmentato richiede O(Analisi della complessità) spazio ausiliario.

Complessità temporale:

La complessità temporale di un algoritmo standard del Crivello di Eratostene è O(n*log(log(n))). La motivazione di questa complessità è discussa di seguito.

Per un dato numero n, il tempo necessario per contrassegnare un numero composto (ovvero un numero non primo) è costante. Pertanto, il numero di volte in cui il ciclo viene eseguito è pari a:

n/2 + n/3 + n/5 + n/7 + ……∞

= n* (1/2 + 1/3 + 1/5 + 1/7 +…….∞)

La progressione armonica della somma dei numeri primi può essere dedotta come log(log(n)):

(1/2 + 1/3 + 1/5 + 1/7 +…….∞) = log(log(n))

Quindi, la complessità temporale sarà:

T(n) = n * (1/2 + 1/3 + 1/5 + 1/7 + ……∞)

= n * log(log(n))

Pertanto la complessità temporale è O(n * log(log(n))).

Successivamente imparerai a conoscere Triangolo di Pascal.

DOMANDE FREQUENTI

Qualsiasi numero composto n può essere scritto come prodotto di due fattori, e almeno uno di questi deve essere minore o uguale alla radice quadrata di n. Oltre questo punto, non è necessario indicare i multipli perché ogni numero composto è già stato eliminato.

Il crivello tradizionale alloca O(n) memoria per contrassegnare ogni numero, mentre il crivello segmentato divide l'intervallo in blocchi di dimensione √n e riutilizza la memoria. La versione segmentata è preferibile quando n è molto grande e la RAM è limitata.

Il suo tempo di esecuzione è O(n log log n), che è quasi lineare. Generare tutti i numeri primi inferiori a dieci milioni richiede solo una frazione di secondo su un laptop moderno, rendendo il crivello la scelta pratica più veloce per intervalli piccoli e medi.

I moderni acceleratori di intelligenza artificiale velocizzano le ricerche di numeri primi di grandi dimensioni parallelizzando i crivelli su GPU e TPU. I modelli di apprendimento automatico aiutano anche a prevedere intervalli di candidati promettenti, riducendo il carico di lavoro per i test di primalità di Miller-Rabin e altri utilizzati nella generazione di chiavi RSA.

Sì. I tutor basati sull'IA generano istruzioni passo passo tracQuesti strumenti visualizzano l'eliminazione composita, suggeriscono ottimizzazioni come la fattorizzazione a ruota e spiegano le dimostrazioni in modo interattivo. Aiutano gli studenti a sviluppare l'intuizione per i limiti delle serie armoniche e le argomentazioni sulla complessità alla base del crivello.

Riassumi questo post con: