[C] Numeri primi
Salve, tempo fa lessi su un blog un algoritmo spacciato per veloce che calcolava numeri primi attraverso un realloc su un array costituito da soli numeri primi; si basava sul fatto che un numero è primo solo se non è divisibile per i primi minori. Quindi ottimizzava di gran lunga qualsiasi altro tipo di speculazione matematica non probabilistica. Il fatto è che il realloc, per come veniva eseguito, uccideva la memoria e il processore, facendo perdere molto più tempo rispetto all'algoritmo che prova tutti i numeri minori del numero su cui si esegue il test. Insomma veniva usato male.
Allora mi misi a pensare a come ottimizzare la cosa sviluppando un programma molto veloce (con esclusione dai controlli dei numeri pari e l'iterazione fino alla radice quadrata del numero da testare).
Tuttavia concettualmente il metodo di provare solo i numeri primi rimane quello più veloce, anche se non banale da codificare.
Recentemente mi è venuta un'idea su come aggirare l'ostacolo delle funzioni di realloco che sono molto pesanti (in altri forum mi avevano consigliato di migliorare quell'algoritmo semplicemente riallocando memoria a intervalli di tempo prevedibili per cui si sarebbe trovato un numero primo e soprattutto in quantità sufficienti per non farlo sempre), ma dovrebbe esserci una strada più semplice.
Ho provato cosi ma non riesco a farlo funzionare, c'è un problema a me non evidente, magari concettuale sulla programmazione:
La logica è: inizializzo un vettore con le dimensioni del numero al quale voglio arrivare, salvo tra i primi elementi alcuni numeri primi conosciuti (di numero arbitrario) e successivamente, con la funzione controllo() testo quale numero inserire nel vettore di numeri primi. Una volta controllati i numeri fino al valore specificato posiziono il carattere di terminazione '\0' dopo l'ultimo numero primo trovato (che sarà sicuramente su una posizione minore della dimensione iniziale) e scrivo il vettore su un file.
Cosa sto sbagliando?
Allora mi misi a pensare a come ottimizzare la cosa sviluppando un programma molto veloce (con esclusione dai controlli dei numeri pari e l'iterazione fino alla radice quadrata del numero da testare).
Tuttavia concettualmente il metodo di provare solo i numeri primi rimane quello più veloce, anche se non banale da codificare.
Recentemente mi è venuta un'idea su come aggirare l'ostacolo delle funzioni di realloco che sono molto pesanti (in altri forum mi avevano consigliato di migliorare quell'algoritmo semplicemente riallocando memoria a intervalli di tempo prevedibili per cui si sarebbe trovato un numero primo e soprattutto in quantità sufficienti per non farlo sempre), ma dovrebbe esserci una strada più semplice.
Ho provato cosi ma non riesco a farlo funzionare, c'è un problema a me non evidente, magari concettuale sulla programmazione:
#include <stdio.h> int controllo(long long int num, long long int vett[], long long int tmp){ long long int i, nop=0; for(i=0; i<=tmp; i++){ if(num%vett[i] == 0){ nop++; } } if(nop == 0){ return 1; }else{ return 0; } } int main(){ long long int dim, i, tmp; char file[] = "Primes.txt"; printf("Calcolatore di numeri primi\n"); printf("Inserisci fino a che numero si vuole cercare: "); scanf("%lld", &dim); long long int vett[dim]; /* for(i=0; i<=dim; i++){ vett[i] = 0; } */ vett[0] = 1; vett[1] = 2; vett[2] = 3; vett[3] = 5; tmp = 4; //Calcoli printf("\n\aATTENZIONE: la durata del calcolo dipende dal limite impostato!\n\tCalcolo in corso, attendere prego...\n"); for(i=0; i<=dim; i++){ if(controllo(i, vett, tmp) == 1){ tmp++; vett[tmp] = i; } } vett[tmp+1] = '\0'; //Scrittura risultato printf("\nScrittura su file..."); FILE *fp; fp = fopen(file, "w"); for(i=0; i<=tmp; i++){ fprintf(fp, "%lld\n", vett[i]); } fclose(fp); printf("\nNumeri scrittu sul file Primes.txt\n\n"); system("PAUSE"); return 0; }
La logica è: inizializzo un vettore con le dimensioni del numero al quale voglio arrivare, salvo tra i primi elementi alcuni numeri primi conosciuti (di numero arbitrario) e successivamente, con la funzione controllo() testo quale numero inserire nel vettore di numeri primi. Una volta controllati i numeri fino al valore specificato posiziono il carattere di terminazione '\0' dopo l'ultimo numero primo trovato (che sarà sicuramente su una posizione minore della dimensione iniziale) e scrivo il vettore su un file.
Cosa sto sbagliando?
Risposte
Ecco, ho capito dove stava l'errore, puramente matematico, era il primo elemento del vettore.
Ecco il codice corretto (anche con una piccola ottimizzazione della funzione di controllo).
P.S.
Non ho usato le funzioni di allocamento dinamico perchè molto pesanti, volevo valutare la velocità senza la libreria stdlib.h.
Ecco il codice corretto (anche con una piccola ottimizzazione della funzione di controllo).
#include <stdio.h> int controllo(register long long int num, long long int vett[], register long long int tmp){ register long long int i, nop; nop = 0; for(i=0; i<=tmp; i++){ if(num%vett[i] == 0){ nop++; if(nop != 0){ goto RITORNO; } } } RITORNO: if(nop == 0){ return 1; }else{ return 2; } } int main(){ long long int dim, i, tmp; char file[] = "Primes.txt"; printf("Calcolatore di numeri primi\n"); printf("Inserisci fino a che numero si vuole cercare: "); scanf("%lld", &dim); long long int vett[dim]; vett[0] = 2; vett[1] = 2; vett[2] = 3; vett[3] = 5; tmp = 3; //Calcoli printf("\n\aATTENZIONE: la durata del calcolo dipende dal limite impostato!\n\tCalcolo in corso, attendere prego...\n"); for(i=6; i<=dim; i++){ if(controllo(i, vett, tmp) == 1){ tmp++; vett[tmp] = i; } } vett[0] = 1; vett[tmp+1] = '\0'; //Scrittura risultato printf("\nScrittura su file..."); FILE *fp; fp = fopen(file, "w"); for(i=0; i<=tmp; i++){ fprintf(fp, "%lld\n", vett[i]); } fclose(fp); printf("\nNumeri scritti sul file Primes.txt\n\n"); system("PAUSE"); return 0; }
P.S.
Non ho usato le funzioni di allocamento dinamico perchè molto pesanti, volevo valutare la velocità senza la libreria stdlib.h.