Nombres premiers (RAM / Vitesse)

Résolu/Fermé
Utilisateur anonyme - Modifié par EchoIsON le 23/03/2016 à 18:28
 Utilisateur anonyme - 26 mars 2016 à 17:20
Bonsoir.

Voilà, j'aimerais créer un programme en C affichant le plus grand nombre premier inférieur ou égal au nombre rentré par l'utilisateur. Je voudrais également que ce programme soit à la fois rapide, et utilise peu de mémoire vive.

Voici deux programmes, le premier utilise le reste de la division euclidienne pour déterminer si le nombre est premier ou pas, n'utilise pas beaucoup de mémoire vive mais est assez lent (0.6s pour venir à bout de 1 million de nombres). Le deuxième utilise le crible d'Eratosthene et n'utilise que des additions (consomme énormement de mémoire) et est relativement rapide (0.036s pour 1 million de nombres).

Avec le modulo :

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
typedef enum
{False = 0, True = 1}
Bool;
 
int main()
{
    int n, la;
    int k = 1;
    int p = 500;
    Bool test = True;
 
for(n = 3; n <= p; n+=2)
{
    test = True;
    double fs = floor(sqrt(n));
    int j;
        for(j = 2; j <= fs; j++)
        {
            if(n % j == 0)
            {
                test = False;
                break;
            }
        }
        if(test)
        {
        k ++;
        la = n;
        }
}
    printf("%d\n", la);
    printf("\nParmi les %d premiers nombres, %d sont premiers.\n", p, k);
    return 0;
}


Avec le crible d'Eratosthene :

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
#define NB 1000000
 
typedef enum
{False = 0 , True = 1}
Bool;
 
const int p = NB;
Bool arr[NB] = {False};
 
int main() {
    int k = 0;
    int i, la;
    for (i = 2; i < p; i++)
    {
        if (!arr[i])
        {
            for (int m = i << 1; m < p; m += i)
            {
                arr[m] = True;
            }
 
            k++;
            la = i;
        }
    }
    printf("%d\n", la);
    printf("\nParmi les %d premiers nombres, %d sont premiers.\n", p, k);
    return 0;
}


Comment puis-je faire pour "combiner" les deux et avoir un programme à la fois rapide et qui consomme peu de mémoire (par exemple en utilisant tous les coeurs de mon processeur) ?
Merci pour votre aide.

<\EchoIsON>
A voir également:

1 réponse

Franck7511 Messages postés 14296 Date d'inscription jeudi 24 décembre 2009 Statut Membre Dernière intervention 10 août 2017 1 121
Modifié par Franck7511 le 23/03/2016 à 23:03
Pour ton problème, tu peux "raccourcir" ta table d'Eratosthène en utilisant le postulat de Bertrand: https://en.wikipedia.org/wiki/Bertrand%27s_postulate
Regarde la partie "Better results" pour des résultats encore plus optimisés...

Au lieu de stocker un tableau de 1 à X (où X est l'entrée de l'utilisateur), tu peux aller de 1 à sqrt(X) puis de X/2 à X (ou bien mieux si X est assez grand !), d'où l'économie de mémoire conséquente (tu peux faire deux tableaux)

L'idée est de faire exactement comme le critère d'Eratosthène normal mais en excluant la partie inutile, donc ça sera encore plus rapide car moins de données à traiter.

Une idée assez immédiate est de virer les nombres pairs, tu peux économiser la moitié de ta mémoire.

Ceci dit, cet algorithme ne se prête pas très bien au Multithreading mais ça reste possible visiblement... J'ai trouvé ça : https://mmfcordeiro.files.wordpress.com/2012/10/mmfcordeiro-parallelization-of-the-sieve-of-eratosthenes.pdf
Si tu connais déjà les nombres premiers entre 1 et sqrt(X) c'est faisable facilement en parallèle sur l'autre tableau (X/2 -> X)...
PS: C'est exactement l'"Optimization 2" qu'ils proposent...
0
Utilisateur anonyme
26 mars 2016 à 17:20
Merci beaucoup pour votre réponse.
0