El enlace de Marc B muestra un algoritmo simple y correcto, escrito por NSLogan. Escribí una pequeña modificación para mostrar algunos intercambios de tamaño/velocidad. Pensé que lo compartiría por interés.
En primer lugar, el código:
#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;
}
(Perdona el mensaje de error por no ser precisa cuando se define USE_BITS ...)
He comparado tres maneras diferentes de almacenar las variables booleanas que sugirió Peoro. Un método realmente usa bits, el segundo toma un byte completo, y el último usa una palabra de máquina completa. Una suposición ingenua sobre cuál es la más rápida podría ser el método de palabras de la máquina, ya que cada marcador/booleano es tratado con más 'naturalidad' por su máquina. Los horarios para el cálculo de los números primos hasta 100 millones en mi máquina fueron los siguientes:
Bits: 3.8s Caracteres: 5.8S M-palabras: 10.8s
Es interesante notar que incluso todo lo feo el cambio de bit necesario para representar un booleano con solo un bit es aún más rápido en general. Mi conjetura es que el almacenamiento en caché y la localidad de referencia parecen superar las ~ instrucciones adicionales. ¡Además, terminas usando 1/nth la memoria del método n-bit-machine-word!
Sí, el tamiz sencillo es lento. Si publica lo que tiene hasta ahora, tal vez alguien puede ayudarlo a mejorarlo. – aschepler
Publique su código por favor – Elalfer
5 segundos de búsqueda en Google: http://www.dreamincode.net/code/snippet3315.htm –