Il collegamento di Marc B mostra un algoritmo semplice e corretto, corretto da NSLogan. Ho scritto una leggera modifica per mostrare alcuni compromessi di dimensioni/velocità. Pensavo di condividere per interesse.
In primo luogo, il codice:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <time.h>
#define USE_BITS
#ifdef USE_BITS
#define alloc_prime char *prime = calloc(i/8,sizeof(*prime));
#define set_not_prime(x) prime[x/8]|= (1<<(x%8))
#define is_prime(x) (!(prime[x/8]&(1<<(x%8))))
#endif
#ifdef USE_CHAR
#define alloc_prime char *prime = calloc(i,sizeof(*prime));
#define set_not_prime(x) prime[x] = 1
#define is_prime(x) (prime[x] == 0)
#endif
#ifdef USE_SIZE_TYPE
#define alloc_prime size_t *prime = calloc(i,sizeof(*prime));
#define set_not_prime(x) prime[x] = 1
#define is_prime(x) (prime[x] == 0)
#endif
int main(){
int i;
printf("Find primes up to: ");
scanf("%i",&i);
clock_t start, stop;
double t = 0.0;
assert((start = clock())!=-1);
//create prime list
alloc_prime;
int c1, c2, c3;
if(!prime){
printf("Can't allocate %zu bytes!\n",i*sizeof(*prime));
exit(1);
}
//set 0 and 1 as not prime
set_not_prime(0);
set_not_prime(1);
//find primes then eliminate their multiples (0 = prime, 1 = composite)
for(c2 = 2;c2 <= (int)sqrt(i)+1;c2++){
if(is_prime(c2)){
c1=c2;
for(c3 = 2*c1;c3 <= i+1; c3 += c1){
set_not_prime(c3);
}
}
}
stop = clock();
t = (double) (stop-start)/CLOCKS_PER_SEC;
//print primes
for(c1 = 0; c1 < i+1; c1++){
if(is_prime(c1))printf("%i\n",c1);
// if(prime[c1] == 0) printf("%i\n",c1);
}
printf("Run time: %f\n", t); //print time to find primes
return 0;
}
(perdonate il messaggio di errore per non essere precisi quando USE_BITS è definito ...)
Ho confrontato tre diversi modi di memorizzare le variabili booleane che suggerito da Peoro. Un metodo utilizza effettivamente bit, il secondo richiede un intero byte e l'ultimo utilizza un'intera parola macchina. Un'ingenua ipotesi su quale sia il più veloce potrebbe essere il metodo della parola macchina, dal momento che ogni flag/booleano viene trattato in modo più "naturale" dalla tua macchina. I tempi per calcolare i numeri primi fino a 100 milioni sulla mia macchina è stata la seguente:
Bits: 3.8s Chars: 5.8S M-parole: 10.8s
E 'interessante notare che anche tutto il brutto lo spostamento di bit necessario per rappresentare un booleano con un solo bit è ancora più veloce nel complesso. La mia congettura è che il caching e la località di riferimento sembrano superare le istruzioni extra ~ 3. Inoltre, si finisce usando 1/nth della memoria del metodo n-bit-machine-word!
Sì, il setaccio semplice è lento. Se pubblichi ciò che hai finora, forse qualcuno può aiutarti a migliorarlo. – aschepler
Inserisci il tuo codice per favore – Elalfer
5 secondi di googling: http://www.dreamincode.net/code/snippet3315.htm –