[Python] numeri primi

Enrico Franchi enrico.franchi a gmail.com
Mer 3 Ago 2011 17:39:05 CEST


Marco Beri wrote:
> Ma ce le fai vedere o no queste 5 e poi 15 righe? O sono scienza
> segreta?  :-)

def erat_basic(buffer, end):
     limit = int(math.ceil(math.sqrt(end)))
     buffer[0] = buffer[1] = 0
     for i in xrange(2, limit):
         if buffer[i]:
             buffer[np.arange(2*i, end, step=i)] = 0

Buffer glielo passo da fuori ed e' una robba tipo:

np.ones(size+1, dtype=np.bool)


La versione da 15 fa un briciolo di unrolling a mano:

def erat(buffer, end):
     limit = int(math.ceil(math.sqrt(end)))
     buffer[0] = buffer[1] = 0
     buffer[np.arange(4, end, step=2)] = 0
     buffer[np.arange(9, end, step=3)] = 0
     buffer[np.arange(25, end, step=5)] = 0
     buffer[np.arange(49, end, step=7)] = 0
     buffer[np.arange(121, end, step=11)] = 0
     buffer[np.arange(169, end, step=13)] = 0
     buffer[np.arange(289, end, step=17)] = 0
     buffer[np.arange(361, end, step=19)] = 0
     for i in xrange(23, limit):
         if buffer[i]:
             buffer[np.arange(2*i, end, step=i)] = 0



Siccome pero' a me le funzioni di piu' di 10 righe mi infastidiscono,
sto lavorando su una cosa come:

def erat(buffer, end, small_primes=[2, 3, 5, 7]):
     limit = int(math.ceil(math.sqrt(end)))
     buffer[0] = buffer[1] = 0

     for p in small_primes:
         buffer[np.arange(p*p, end, step=p)] = 0

     for i in xrange(p+1, limit):
         if buffer[i]:
             buffer[np.arange(2*i, end, step=i)] = 0


Che da risultati comparabili a patto di scegliere bene l'array di primi 
iniziale. Qualcosa come:

def small_primes(end):
     limit = int(math.ceil(math.sqrt(end)))
     buffer = np.ones(end, dtype=np.bool)
     buffer[0] = buffer[1] = 0
     for i in xrange(2, limit):
         if buffer[i]:
             buffer[np.arange(2*i, end, step=i)] = 0
     return np.nonzero(buffer)[0]

funziona.

% time python erat2.py 100000000 10000
(array([       2,        3,        5, ..., 99999959, 99999971, 99999989]),)
python erat2.py 100000000 10000  5.99s user 0.88s system 97% cpu 7.022 total

Qui per dire gli do in pasto i primi 10000 primi. Bisogna un po' capire 
quale e' un buon valore per l'array iniziale.


-- 
.
..: -enrico-



Maggiori informazioni sulla lista Python