Ver Mensaje Individual
  #15 (permalink)  
Antiguo 31/07/2014, 08:44
Pantaláimon
 
Fecha de Ingreso: julio-2006
Ubicación: Barcelona
Mensajes: 244
Antigüedad: 18 años, 4 meses
Puntos: 32
Respuesta: Buscando números primos, con la criba de Eratóstenes

Vaya, era la variable i2, que debería tener en todo momento el valor de 2*i pero no lo tuvo por un despiste. El código ahora apenas mejora el tuyo en velocidad:

Código C:
Ver original
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <stdlib.h>
  4.  
  5. int main(void) {
  6.    unsigned top = 1000000000;
  7.    unsigned rtop = sqrt(top);
  8.    unsigned char* nums = calloc( top, sizeof *nums);
  9.    unsigned primsTop = 1.2 * (top / log(top)); /* apaño para ahorrar memoria */
  10.    unsigned* prims = calloc( primsTop, sizeof *prims);
  11.    unsigned n; /* contador primos */
  12.    unsigned i, i2, ii;
  13.    unsigned j, k, l, x;
  14.  
  15.    k = x = nums[4] = nums[6] = nums[8] = 1;
  16.    l = n = prims[0] = 2;
  17.    i = prims[1] = 3;
  18.    l = 5;
  19.    i2 = i + i;
  20.    ii = i * i;
  21.  
  22.    /* calculo de la tabla */
  23.    for (i = 3; i <= rtop; i = prims[x], i2 = 2*i) {
  24.  
  25.       /* todo numero j tal que l <= j <= i*i-1 con nums[j] == 0 es primo */
  26.      
  27.       ii = i*i;
  28.       /* printf("A) calcula primos de %d a %d\n", l, ii-1); */
  29.       for (j = l; j < ii; j += 2)
  30.          if(nums[j] == 0){
  31.             prims[n++] = j;
  32.             //printf("%d\n", prims[n-1]);
  33.          }
  34.       l = ii+2;
  35.      
  36.       /* Dado k que va de x a n-1, se descartan los compuestos i*prims[k]    *
  37.        * donde se ve que i == prims[x]                                       *
  38.        * (Es una forma de evitar descartar números que ya están descartados) */
  39.       /* printf("B) descartar primos de %d a %d\n", i*prims[x], i*prims[n-1]); */
  40.       for (k = x; k < n; ++k) {
  41.          j = i*prims[k];
  42.          if (j >= top) break;
  43.          nums[j] = 1;
  44.          /* printf("%d\n", j); */
  45.       }
  46.      
  47.       /* a partir de aquí, se descartan los compuestos de la manera común */
  48.  
  49.       if (j < top) j += i2;
  50.       /* printf("C) descartar primos de %d a %d\n", j, top-1); */
  51.       for (; j < top; j += i2) {
  52.          if(!nums[j]) {
  53.             nums[j] = 1;
  54.             /*printf("%d\n", j);*/
  55.          }
  56.       }
  57.       ++x;
  58.       //printf("%d\n", prims[x]);
  59.    }
  60.  
  61.    /* calcular resto de primos */
  62.    for (i = prims[n-1]+2; i < top; i += 2) {
  63.       if (nums[i] == 0) {
  64.          prims[n] = i;
  65.          ++n;
  66.       }
  67.    }
  68.    /*
  69.    for(i = 0; i < n; ++i) {
  70.       printf("%d, ", prims[i]);
  71.    }
  72.    */
  73.    printf("%d primos\n", n);
  74.    printf("%f\n", (double)n/primsTop);
  75.    free(nums);
  76.    free(prims);
  77.  
  78.    return 0;
  79. }

Edit: añadida nueva modificación que mejora unas décimas.

Un saludo!
__________________
github.com/xgbuils | npm/xgbuils

Última edición por Pantaláimon; 31/07/2014 a las 10:00