begin process at 2010 02 09 22:52:35
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > RECHERCHE DE NOMBRES PREMIERS PAR LE CRIBLE D'ERATOSTHENE

RECHERCHE DE NOMBRES PREMIERS PAR LE CRIBLE D'ERATOSTHENE


 Information sur la source

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Maths & Algorithmes Classé sous :premiers, premier, eratosthène, crible, michel Niveau :Initié Date de création :27/06/2006 Date de mise à jour :07/07/2006 11:50:48 Vu / téléchargé :8 322 / 201

Auteur : _michel

Ecrire un message privé
Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Affiche tous les nombres premiers de 0 à n sur la sortie standard d'après le crible d'Eratosthène.

Source

  • /*
  • * PREMIER.C - Affiche tous les nombres premiers de 0 à n sur la
  • * sortie standard, par le crible d'Eratosthène.
  • * Testé sur un Pentium 4, l'obtention de la liste de tout les nombres
  • * premiers de 0 à 1 000 000 000 (552 807 324 octets) né‚cessite 1mn 18s.
  • *
  • * Développé par Michel Blancard.
  • * Version 2.2
  • * Dernière modification le 06/07/2006.
  • */
  • #include <stdio.h>
  • #include <math.h>
  • #include <stdlib.h>
  • #include <conio.h>
  • void main(int argc, char **argv)
  • {
  • unsigned char *tableau;
  • unsigned long i, j;
  • unsigned long taille;
  • unsigned long nbr_max;
  • if(argc < 2)
  • {
  • cprintf("Syntaxe incorrecte.\n\r");
  • cprintf("Syntaxe correcte : \"premier nbr_max [> *.*]\".\n\r");
  • cprintf("nbr_max - maximum pour la recherche");
  • return;
  • }
  • if((argv[1][0] < '0')&&(argv[1][0] > '9'))
  • {
  • cprintf("Syntaxe incorrecte.\n\r");
  • cprintf("Syntaxe correcte : \"premier nbr_max [> *.*]\".\n\r");
  • cprintf("nbr_max - maximum pour la recherche\n\r");
  • return;
  • }
  • nbr_max = atol(argv[1]) + 1;
  • taille = (nbr_max + 14) >> 4; // On ne stocke que les nombres impaires.
  • if((tableau = malloc(taille)) == NULL)
  • {
  • cprintf("Memoire disponible insuffisante.\n\r");
  • return;
  • }
  • for(i=1; i<taille; i++)
  • {
  • tableau[i] = 255; // Initialise les bits … 1 sauf le premier
  • } // (nombre 1 non premier de toute fa‡on)
  • tableau[0]=254; // 252 <=> 11111110
  • /*
  • * Raye tout les nombres non premiers (environ 40 % du temps d'execution).
  • */
  • for(i = 1; i <= (unsigned long)sqrt((double)nbr_max) / 2; i++)
  • {
  • if(tableau[i >> 3] & (unsigned char)(1 << (i & 7)))
  • // si c'est un nombre premier
  • { // alors on ‚limine tout ses multiples
  • for(j = (4 * i * i) + (4 * i) + 1; j < nbr_max; j += (i * 4) + 2)
  • {
  • tableau[j >> 4] = tableau[j >> 4] & (unsigned char)(~(unsigned char)(1 << (((j - 1) / 2) & 7)));
  • }
  • }
  • }
  • /*
  • * Affiche les nombres premiers (environ 60 % du temps d'execution).
  • */
  • if(nbr_max > 2)
  • {
  • printf("2\n"); // le nombre 2 n'est pas dans la liste
  • }
  • for(i=1; i<nbr_max / 2; i++)
  • {
  • if((tableau[i >> 3] & (unsigned char)(1 << (i & 7))) > 0)
  • {
  • printf("%lu\n", (i * 2) + 1);
  • }
  • }
  • free(tableau);
  • }
/*
 *  PREMIER.C - Affiche tous les nombres premiers de 0 à n sur la
 *  sortie standard, par le crible d'Eratosthène.
 *  Testé sur un Pentium 4, l'obtention de la liste de tout les nombres
 *  premiers de 0 à 1 000 000 000 (552 807 324 octets) né‚cessite 1mn 18s.
 *
 *  Développé par Michel Blancard.
 *  Version 2.2
 *  Dernière modification le 06/07/2006.
 */

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>

void main(int argc, char **argv)
{
  unsigned char *tableau;
  unsigned long i, j;
  unsigned long taille;
  unsigned long nbr_max;

  if(argc < 2)
  {
    cprintf("Syntaxe incorrecte.\n\r");
    cprintf("Syntaxe correcte : \"premier nbr_max [> *.*]\".\n\r");
    cprintf("nbr_max - maximum pour la recherche");
    return;
  }
  if((argv[1][0] < '0')&&(argv[1][0] > '9'))
  {
    cprintf("Syntaxe incorrecte.\n\r");
    cprintf("Syntaxe correcte : \"premier nbr_max [> *.*]\".\n\r");
    cprintf("nbr_max - maximum pour la recherche\n\r");
    return;
  }

  nbr_max = atol(argv[1]) + 1;
  taille = (nbr_max + 14) >> 4;    // On ne stocke que les nombres impaires.
  if((tableau = malloc(taille)) == NULL)
  {
    cprintf("Memoire disponible insuffisante.\n\r");
    return;
  }

  for(i=1; i<taille; i++)
  {
    tableau[i] = 255;          // Initialise les bits … 1 sauf le premier
  }                            // (nombre 1 non premier de toute fa‡on)
  tableau[0]=254;              // 252 <=> 11111110

  /*
   * Raye tout les nombres non premiers (environ 40 % du temps d'execution).
   */
  for(i = 1; i <= (unsigned long)sqrt((double)nbr_max) / 2; i++)
  {
    if(tableau[i >> 3] & (unsigned char)(1 << (i & 7)))
			       // si c'est un nombre premier
    {                          // alors on ‚limine tout ses multiples
      for(j = (4 * i * i) + (4 * i) + 1; j < nbr_max; j += (i * 4) + 2)
      {
        tableau[j >> 4] = tableau[j >> 4] & (unsigned char)(~(unsigned char)(1 << (((j - 1) / 2) & 7)));
      }
    }
  }

  /*
   * Affiche les nombres premiers (environ 60 % du temps d'execution).
   */
  if(nbr_max > 2)
  {
    printf("2\n");    // le nombre 2 n'est pas dans la liste
  }
  for(i=1; i<nbr_max / 2; i++)
  {
    if((tableau[i >> 3] & (unsigned char)(1 << (i & 7))) > 0)
    {
      printf("%lu\n", (i * 2) + 1);
    }
  }

  free(tableau);
}

 Conclusion

Pour plus d'informations sur le fonctionnement, regardez sur internet -> Eratosthène.
En gros, un bit est alloué à chaque nombre impaires, les nombres pairs ne sont pas premiers de toute façon (à part 2). Au début, tout les bit valent 1 (on considère tout premier).
En suite, pour chaque nombre premier trouvé (dont le bit vaut 1), on élimine (on met les bits à 0) tout ses multiples impaires jusqu'à n(maximum).
Finalement, on affiche tout les nombres qui n'ont pas été éliminés.

Concrètement, sur une suite de 0 à 15 :
0 et 1 ne sont pas premiers par définition.
2 est premier par définition.
4, 6, 8, 10, 12, 14 ne sont pas stockés(pairs).
3 est premier.
->Il élinine ses multiples impaires (9 et 15).
5 est premier.
->10 est pair et 15 est déjà éliminé par 3, il n'élimine donc rien.
7 est premier.
->Idem pour 14.
9 est multiple du nombre premier 3.
11 est premier.
->Il n'a aucun multiple dans la suite.
13 est premier.
->Idem.
15 est multiple du nombre premier 3.

Les nombres premiers sont donc : 2, 3, 5, 7, 11, 13.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

28 juin 2006 14:34:57 :
Cette version est beaucoup plus performante, le temps d'execution passe de 7 secondes à un quart, et ne prend que 1 cinquième de plus de mémoire !
28 juin 2006 14:41:16 :
Cette version est beaucoup plus performante, le temps d'execution passe de 7 secondes à un quart, et ne prend que 1 cinquième de plus de mémoire !
28 juin 2006 14:46:22 :
Cette version est beaucoup plus performante, le temps d'execution passe de 7 secondes à un quart, et ne prend que 1 cinquième de plus de mémoire ! Remodification pour cause de fautes d'orthorgraphe.
07 juillet 2006 11:50:48 :
Maintenant, mon code tient à peu près la route. Tout les calculs inconpréhensibles ont pour but de ne stocker que les nombres impaires.

 Sources du même auteur

PROXY IRC SIMPLE (WINDOWS/WINSOCK)
Source avec Zip BASE POUR L'UTILISATION DU GDI (API WINDOWS)
Source avec Zip SQUELETTE DE MOTEUR 3D
Source avec Zip Source avec une capture REPRÉSENTATIONS GRAPHIQUE D'ONDES, RECHERCHE OPTIMISATIONS.

 Sources de la même categorie

Source avec Zip OPERATION SUR LES MATRICES CARREES AVEC CLASSE GENERIQUE par chouhad
Source avec une capture OPÉRATIONS SUR MATRICES C++ par Minilogus
[DEV-C++] CALCUL DE LA RACINE CARRÉE D'UN RÉEL par Jhep
PROGRAMME QUI CALCUL LE PPCM ET LE PGCD par AnoSantino
EVALUER UNE EXPRESSION MATHÉMATIQUE par begueradj

 Sources en rapport avec celle ci

Source avec Zip FACTORISATION D'UN NOMBRE EN NOMBRE PREMIER par Tearsofdestiny
Source avec une capture FACTORISATION D'UN NOMBRE par Faibbus
Source avec Zip SQUELETTE DE MOTEUR 3D par _michel
Source avec Zip GÉNÉRATION DE NOMBRES PREMIERS ET STOCKAGE DANS UN FICHIER par visdev
NOMBRES PREMIERS - ERATOSTHENE QUASI ILLIMITÉ par bzrd

Commentaires et avis

Commentaire de _michel le 27/06/2006 14:34:09

Je cherche à optimiser mon algo.
Merci de me donner des conseils.

Commentaire de Pole4 le 27/06/2006 14:46:06

Utilise le crible d'Erathostène.
On part d'une liste
2 3 4 5 6 7 8 9 10
On prend le premier nombre : 2->1 er nombre premier
On l'enlève.
On enlève tous ses multiples.
3 5 7 9

On prend le premier nombre : 3-2ème nombre premier
On l'enlève.
On enlève tous ses multiples.
5 7
5 est plus grand que la racine carré de 10, on stoppe.

Normalement pour l'implémentation, on prend une liste qu'on a mis à 0, et à chaque fois qu'on effectue l'opération on enlève, on met la case correspondante à 1. Pour prendre le premier nombre, on recherche le premier nombre != 0.

Pole.


Commentaire de _michel le 27/06/2006 15:06:48

Merci, je vais l'essayer pour voir si c'est plus rapide (vu que le 9999ème nbr 1er vaut environ 104000, je suis pas encore trop sur que ca va être possible niveau mémoire).

Commentaire de BruNews le 27/06/2006 18:00:17 administrateur CS

Les nombres premiers et les calculettes sont les sujets récurrents sur cppfrance.
http://www.google.com/custom?domains=cppfrance.com&q=premier&sa=Rechercher&sitesearch=cppfrance.com

Ne sera pas conservé.

Commentaire de Noxk le 28/06/2006 10:01:34

for(i=0; i<Taille; i++)
Tab[i] = i + 2;

for (i=2; i<Taille/2; i++)
{
if (!Tab[i])
continue;

for (j=i*2; j<Taille; j += i)
{
if (Tab[j])
Tab[j] = 0;
}
}

voila le bout de code que j'avais du utiliser pour calculer les nombres premiers. Si ca peut servir...

Commentaire de _michel le 28/06/2006 14:37:39

Ca y est, j'ai modifié mon code, il est beaucoup plus rapide, mais peut-on encore l'optimiser?

Commentaire de vlostanlen le 28/06/2006 16:08:57

L'algorithme est rapide est intéressant, mais je trouve qu'il est plus utile de savoir si un nombre est premier, ou quels nombre sont premiers dans une plage de nombres. Bon codage, mais   "tournure" pas très judicieuse à mon goût.

Commentaire de _michel le 28/06/2006 16:15:35

Donc, il serai peut être interessant de faire un programme qui donne touts les diviseurs d'un nombre.
Si les seuls diviseurs sont 1 et ce nombre, il est premier.

Commentaire de _michel le 28/06/2006 16:34:39

Ha oui, j'oubliais, il est conseillé de changer la sortie standard, pour éviter d'afficher 10000 lignes à l'écran.
Pour ceux qui ne savent pas comment on fait , on tape :
"premier > fichier.txt"
au lieu
"premier"
L'inconvénient est qu'on ne peut pas executer le programme de l'explorateur Windows, mais à partir d'une invite de commande.

Commentaire de BruNews le 28/06/2006 18:05:46 administrateur CS

_michel,
une prochaine fois évite les mises à jour si j'ai indiqué que ça ne sera pas conservé, ce serait perdre du temps.
Je vais donc exceptionnellement laisser cette source mais rappelle toi bien à l'avenir de controler que le sujet n'est pas déjà traité en de nombreux exemplaires parce qua ce sera suppression à tout coup, la place sur nos serveurs n'est pas infinie.

Bonne continuation.

Commentaire de _michel le 29/06/2006 12:30:26

BruNews,
D'abord merci d'avoir conservé cette source, cela me permettra de faire progresser l'algorythme, si c'est encore possible.
Ensuite, j'ai moi-même recherché, sur la totalité des codes sources, ceux qui font référence à premier, premiers, Eratosthène...
Je n'ai trouvé que le mien en C, me serais-je trompé dans ma recherche ?
Si c'est le cas, veuiller m'indiquer ceux que je n'ai pas su trouver, afin de m'en inspirer si c'est utile.
Enfin, je reconnais que j'étais bien conscient que ma source était destinée à être supprimer, en revanche je voulais bénéficier du surcis pour connaitre l'avis d'autres developpeurs, et mes mises à jours n'ont eu pour but que de leurs présenter la version la plus récente, et de corriger de nombreuses fautes d'orthographes.

Salutations.

Commentaire de Pole4 le 29/06/2006 12:55:15

En réponse à un message plus haut, oui on peut l'optimiser.

En mémoire, en ne stockant qu'un nombre sur 2, les nombres impairs (ne pas oublier 2).
En temps, il faut remplacer :
-les pow(2,x%8) par 1<<(x&7)
-les x/8 par x>>3
-à part pour 2, on peut utiliser une incrément de j qui est 2*i
-on peut commencer pour j à i*i
-plus compliqué qu'au dessus, prendre une variable qui contient j/8, et une autre j%8, et à chaque fois, ajouter i%8, sur la variable de j%8 et si c'est >8, enlever 8 à cette variable et incrémenter l'autre (valable pour la version qui utilise les nb pairs et impairs, à modifier pour l'autre).
Avec ça, on peut aller beaucoup plus loin que 100000. (le record est 10^16)

Autre optimisation algorithmique : utiliser le crible d'Atkin.

Pole.

Commentaire de ncoder le 29/06/2006 13:38:18

Je te propose :

http://www.cppfrance.com/codes/NOMBRES-PREMIERS-CRIBLE-ERATHOSTENE_24873.aspx

http://www.cppfrance.com/codes/RECHERCHE-NOMBRES-PREMIERS-AVEC-CRIBLE-ERATOSTHENE_9715.aspx

ou encore

http://www.cppfrance.com/codes/CRIBLE-ERATOSTHENE_10945.aspx

A+ bonne programmation

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Nombres premiers en C Urgent [ par maxfrancky ] il me faut réaliser un programme permettant de lister les n premier nombres premier n utilisnat une liste chainée de structure contenant le nombre pre Nombres premiers... corrigez moi svp =3 [ par nisso13 ] Salut, voila je m'explique, je voudrais faire un programme qui me liste les nombres premiers inferieurs à 1000... je l'ai fait mais il a une erreur qu nombre premier [ par igor941 ] bonjour je suis etudiant et j'ai un tp à réaliser j'aurai besoin d'une petite aide de la part de quelqu'un se debrouillant en C puisque je debute en C Problème pour mettre une Dialog Modale au premier plan [ par ZMJUVENTINO ] Salut, je travaille sur Visual C++ 6Je voudrais à partir de mon application afficher une CDialog modale et qu'elle s'affiche absolument au premier pla comment cliquer sur un bouton virtuellement [ par Billyjijel ] salut ; je pense que ma question est simple relativement; donc j'ai deux boutons, je veux qaud je clique sur le premier j'execute le contenu de deux createfile [ par thegame88 ] Bonjour a tous,Voila j'ai fait un ti prog qui utilise la fonction createfile, mais le premier argument de createfile doit être le chemin du fichier du Recupérer le nom du premier noeud d'un treeview [ par kitcarflo ] J'aimerai pouvoir récupérer dans une variable le mot inscrit dans un treeview. par exemple mon treeview commence par "toto", en enfant de toto on tro rectangle en premier plan [ par minetgrostiti ] Bonjour En c#: J'ai une pictureBox incluant une image le tout dans Form1 Je crée un rectangle (DrawRectangle) pour délimiter une zone de contrôle sur programme nombres premiers [ par I0o0I ] Bonjour, j ai une question pour un programme plutot math mais la question est pas math du tout... c est surement très facile a résoudre. En gros j a factorial factors [ par brahimhakkou ] svp aidez moi c urgentin this problem we want to determine the maximum number of integer terms (excluding1) that can be used to express n! par exemple


Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,326 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales