Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2349 connectés 

  FORUM HardWare.fr
  Programmation
  C

  crible d'Eratosthene en c

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

crible d'Eratosthene en c

n°1552408
lamouche8
Posté le 02-05-2007 à 15:42:47  profilanswer
 

Bonjour,
Je dois trouver les nombres premiers de 1 à 100 en C.
Pour ça, j'ai écris les nombres dans un tableau via ce code :

Code :
  1. #include <stdio.h>
  2. #define nbc 100
  3. main()
  4. {
  5. int tab[nbc], c;
  6. printf("tableau\n" );
  7. for(c=0;c<nbc;c++)
  8. {
  9. tab[c]=c;
  10. }


C'est après que se pose mon problème. Je ne vois pas comment retirer les multiples des nombres premiers.
Si quelqu'un à une idée, merci de bien vouloir m'aider.

mood
Publicité
Posté le 02-05-2007 à 15:42:47  profilanswer
 

n°1552413
_darkalt3_
Proctopathe
Posté le 02-05-2007 à 15:47:35  profilanswer
 

Bah plutot que retirer, tu ajoutes seulement si le nombre est bien premier. Donc tu testes avant.


Message édité par _darkalt3_ le 02-05-2007 à 15:48:03

---------------
Töp of the plöp
n°1552423
MagicBuzz
Posté le 02-05-2007 à 15:54:44  profilanswer
 

indice :
Pour tester si un nombre premier, tu testes juste avec les nombres premiers plus petits ou égaux à racinecarree(nb)
=> ça évite énormément de tests inutiles : genre 51 ne peut pas être un multiple de 50, au maximum tu trouveras des multiples jusqu'à n à n² = 51
=> et pas la peine non plus de tester si le nombre est un multiple d'un nombre qui n'est pas premier
 
y'a d'autres approche bien plus rapides, mais bon, celle-ci est évidente et simple à mettre en place.
 
 
edition : nombre "premiers" je veux dire, pas "entiers" ;)


Message édité par MagicBuzz le 02-05-2007 à 16:00:08
n°1552424
_darkalt3_
Proctopathe
Posté le 02-05-2007 à 15:57:04  profilanswer
 
n°1552444
MagicBuzz
Posté le 02-05-2007 à 16:13:32  profilanswer
 

Faudrait faire des calculs que je sais pas faire, mais j'aimerais bien comparer avec ma méthode. Je ne suis pas sûr que le truc que tu indique soit réellement mieux :??:
 
Quoique pour les grandes valeurs, effectivement ta solution semmble meilleure (mais plus consommatrice en mémoire... j'imagine si on doit rechercher les nombres entiers de 0 à 2^64, ça fait un sacré array à mettre en mémoire, même si c'est un simple array de bit qui est retenu (optimisation à la con qui rend le code imbittable :D)


Message édité par MagicBuzz le 02-05-2007 à 16:15:47
n°1552448
lamouche8
Posté le 02-05-2007 à 16:17:10  profilanswer
 

merci de vos réponses, je vais voir ce que jpeux faire.

n°1552449
_darkalt3_
Proctopathe
Posté le 02-05-2007 à 16:17:50  profilanswer
 

C'est un point de vue algorithmique, pas optimisation (donc mieux ou pas, c'est juste une source de doc en plus).
 
Cela dit, dans la discussion, on trouve une implé en perl:
http://fr.wikipedia.org/wiki/Discu [...] th%C3%A8ne


---------------
Töp of the plöp
n°1552452
MagicBuzz
Posté le 02-05-2007 à 16:22:54  profilanswer
 

Nan pis en fait j'avais pas lu le titre du topic. C'est effectivement une implantation de cet algo qu'il veut, j'ai répondu à côté de la plaque ;)

n°1552457
_darkalt3_
Proctopathe
Posté le 02-05-2007 à 16:27:56  profilanswer
 

ah bah ok lol alors hein ;)


---------------
Töp of the plöp
n°1552461
leto
Posté le 02-05-2007 à 16:32:30  profilanswer
 
mood
Publicité
Posté le 02-05-2007 à 16:32:30  profilanswer
 

n°1552465
MagicBuzz
Posté le 02-05-2007 à 16:35:59  profilanswer
 

Sinon, pour en revenir à cet algo donc...
 
array de byte avec comme valeurs 0 ou 1 (et indices 2..n, je te laisse t'amuser avec un offset pour partir de 0 ;))
 
ensuite, tu les initialise tous à 0, et quand ils sont cochés, tu passes à 1
 
Pour le reste, tu suis bêtement les explications du lien de darkalt3. Ensuite t'as plus qu'à lire les valeurs dans ton tableau, et n'afficher que les indices de ceux qui sont encore à 0

n°1552471
MagicBuzz
Posté le 02-05-2007 à 16:42:49  profilanswer
 

C'est marrant, je ne reconnais pas ma technique dans les tests du gars. Pourtant elle est mieux par exemple que sa première tentative...

n°1552519
MagicBuzz
Posté le 02-05-2007 à 17:42:45  profilanswer
 

LOL.
 
Bon, ben moi je suis nul en analyse de code...
Je pensais pas solution plus rapide pour de petites valeurs et moins rapide pour des grandes...
 
Mais c'est l'inverse :D
 
Bench sur 2 à 100 :


Jusqu'à quelle valeur rechercher des nombres premiers ?
1000
Liste des nombres premiers jusqu'à 1000 :
Da magic solution...
Temps d'exécution : 2 ms
Da pas magic solution...
Temps d'exécution : 0 ms


 
Bench sur 2 à 1000000 :


Jusqu'à quelle valeur rechercher des nombres premiers ?
1000000
Liste des nombres premiers jusqu'à 1000000 :
Da magic solution...
Temps d'exécution : 24507 ms
Da pas magic solution...
Temps d'exécution : 114661 ms


 
Le code (en C#) :

Code :
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. namespace nprems
  6. {
  7.    class Program
  8.    {
  9.        static void Main(string[] args)
  10.        {
  11.            int val;
  12.  
  13.            Console.WriteLine("Jusqu'à quelle valeur rechercher des nombres premiers ?" );
  14.            while (!int.TryParse(Console.ReadLine(), out val))
  15.            {
  16.                Console.WriteLine("Nombre invalide. Recommencez..." );
  17.            }
  18.            Console.WriteLine("Liste des nombres premiers jusqu'à {0} :", val);
  19.  
  20.            Console.WriteLine("Da magic solution..." );
  21.            {
  22.                DateTime d1 = DateTime.Now;
  23.                List<int> prems = new List<int>();
  24.                // On sait que 2 est un nombre premier
  25.                prems.Add(2);
  26.  
  27.                // On sait aussi que seuls les nombres impaires au dessus de 2 peuvent être premiers
  28.                for (int i = 3; i <= val; i += 2)
  29.                {
  30.                    int maxi = (int)Math.Sqrt((double)i);
  31.                    bool gotcha = true;
  32.  
  33.                    // On pacours les nombres premiers déjà existants
  34.                    for (int j = 0, max = prems.Count; j < max; j++)
  35.                    {
  36.                        // Pas besoin de tester les nombres premiers supérieurs à sqrt(i)
  37.                        if (prems[j] <= maxi)
  38.                        {
  39.                            if (i % prems[j] == 0)
  40.                            {
  41.                                // Ce n'est pas un nombre premier
  42.                                gotcha = false;
  43.                                break;
  44.                            }
  45.                        }
  46.                    }
  47.                    if (gotcha)
  48.                    {
  49.                        prems.Add(i);
  50.                    }
  51.                }
  52.  
  53.                foreach (int i in prems)
  54.                {
  55.                    Console.WriteLine(i);
  56.                }
  57.  
  58.                Console.WriteLine("Temps d'exécution : {0} ms", DateTime.Now.Subtract(d1).TotalMilliseconds);
  59.            }
  60.  
  61.            Console.WriteLine("Da pas magic solution..." );
  62.            {
  63.                DateTime d1 = DateTime.Now;
  64.                bool[] nbrs = new bool[val + 1];
  65.                int maxi = val + 1;
  66.                for (int i = 2; i < maxi; i++)
  67.                {
  68.                    nbrs[i] = true;
  69.                }
  70.  
  71.                for (int i = 2; i < maxi; i++)
  72.                {
  73.                    if (nbrs[i])
  74.                    {
  75.                        for (int j = i * 2; j < maxi; j++)
  76.                        {
  77.                            if (nbrs[j])
  78.                            {
  79.                                if (j % i == 0)
  80.                                {
  81.                                    nbrs[j] = false;
  82.                                }
  83.                            }
  84.                        }
  85.                    }
  86.                }
  87.  
  88.                for (int i = 2; i < maxi; i++)
  89.                {
  90.                    if (nbrs[i])
  91.                    {
  92.                        Console.WriteLine(i);
  93.                    }
  94.                }
  95.                                
  96.                Console.WriteLine("Temps d'exécution : {0} ms", DateTime.Now.Subtract(d1).TotalMilliseconds);
  97.            }
  98.  
  99.            Console.ReadKey(true);
  100.        }
  101.    }
  102. }


 
Ceci dit, le problème avec les petites valeurs, c'est je pense la lourdeur de l'objet List<>... Avec un int[] initialisé avec une taille arbitraire ce serait je pense plus rapide aussi dans le cas des toutes petites valeurs :)
 
Evidement, les deux bouts de code retournent le même résultat hein ;)


Jusqu'à quelle valeur rechercher des nombres premiers ?
20
Liste des nombres premiers jusqu'à 20 :
Da magic solution...
2
3
5
7
11
13
17
19
Temps d'exécution : 3 ms
Da pas magic solution...
2
3
5
7
11
13
17
19
Temps d'exécution : 1 ms


Avec une prévérence tout de même pour mon code : j'ai un objet List<int> qui ne contient QUE les nombres premiers à la sortie. Alors qu'avec l'algo d'Eratosthènemachin, je me retrouve avec un array de bool que je dois parcourir à chaque fois pour retrouver les indices désirés...
 
En tout cas, je suis content. L'algo que j'ai mis au point en BASIC sur mon C64 (j'avais quoi... 9 ou 10 ans à l'époque :D) reste meilleur que ce qu'on étudie à la fac :D

Message cité 1 fois
Message édité par MagicBuzz le 02-05-2007 à 17:46:47
n°1552538
matafan
Posté le 02-05-2007 à 18:04:40  profilanswer
 

MagicBuzz, ça t'embêterait de faire du C sur ce forum C ?

Message cité 1 fois
Message édité par matafan le 02-05-2007 à 18:05:06
n°1552544
Taz
bisounours-codeur
Posté le 02-05-2007 à 18:38:40  profilanswer
 

Mais tu nous pourris quoi avec ton C# ? On le sait déjà que tu ne connais pas le C

n°1552546
masklinn
í dag viðrar vel til loftárása
Posté le 02-05-2007 à 18:49:57  profilanswer
 

MagicBuzz a écrit :

LOL.

 

Bon, ben moi je suis nul en analyse de code...
Je pensais pas solution plus rapide pour de petites valeurs et moins rapide pour des grandes...

 

Mais c'est l'inverse :D


Mon code Haskell défonce ton code C# [:klem3i1]
(et en plus il est lisible, et la logique applicative tient en 9 lignes)
(et c'est sans optimisations :o)


Message édité par masklinn le 02-05-2007 à 19:07:51

---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box by throwing away the limits imposed by overbearing genetic regulations? Isn't that a good thing?
n°1552573
MagicBuzz
Posté le 02-05-2007 à 20:06:41  profilanswer
 

Mon code est parfaitement lisible :o
 
Sinon, moi les instructions utiles au code (our le premier par exemple) y'a que 11 lignes, en comptant les déclarations... Alors tes 9 lignes... [:cerveau foudtag]

n°1552575
MagicBuzz
Posté le 02-05-2007 à 20:09:12  profilanswer
 

matafan a écrit :

MagicBuzz, ça t'embêterait de faire du C sur ce forum C ?


1/ je fais du C, j'ai juste rajouté un # derrière [:cerveau boulay]  
2/ en ce qui concerne l'algo, perso, je vois pas de diff avec le C... pour le premier algo, la seule code qui ne se transpose pas nativement en C, c'est le coup du List<int> et j'ai indiqué qu'un simple array de taille arbitraire à la place fait aussi bien l'affaire... quant au second... mise à part la déclaration d'un array qui n'est pas la même, ainsi que le type bool qui n'existe pas je crois, le code compile avec un compilateur C... alors faut pas pousser [:cerveau heink]

n°1552576
masklinn
í dag viðrar vel til loftárása
Posté le 02-05-2007 à 20:10:22  profilanswer
 

MagicBuzz a écrit :

Mon code est parfaitement lisible :o


Absolument pas, c'est la dèche de comprendre la logique applicative.

 

Lisible c'est ça:

Code :
  1. isNull :: Integer -> Bool
  2. isNull = (== 0)
  3.  
  4. isMultiple :: Integer -> Integer -> Bool
  5. isMultiple a b = isNull $ mod a b
  6.  
  7. sieve :: Integer -> [Integer]
  8. sieve limit =
  9.    2 : (sieveHelper [3,5..limit])
  10.  
  11. sieveHelper :: [Integer] -> [Integer]
  12. sieveHelper (x:xs) =
  13.    x:rest
  14.     where
  15.       rest = filter (not . (`isMultiple` x)) xs
 

Et en bonus ça écrase ton code en efficacité:

$ time ./a.out 1000000 > /dev/null

 

real    0m0.150s
user    0m0.137s
sys     0m0.012s
$ time ./a.out 100000000 > /dev/null

 

real    0m15.959s
user    0m15.121s
sys     0m0.614s



Message édité par masklinn le 02-05-2007 à 20:10:42

---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box by throwing away the limits imposed by overbearing genetic regulations? Isn't that a good thing?
n°1552578
MagicBuzz
Posté le 02-05-2007 à 20:14:01  profilanswer
 

y'a qu'un autiste pour trouver ça lisible :o

n°1552579
MagicBuzz
Posté le 02-05-2007 à 20:14:27  profilanswer
 

pis c'est pas du C d'abors, tu va te faire engueuler toi aussi [:magicbuzz]

n°1552580
MagicBuzz
Posté le 02-05-2007 à 20:16:42  profilanswer
 

sinon, ton algo, en français, ça donne quoi ? (parcequ'il a l'air un peu différent du mien, mais je pige pas une ligne sur 15 :D

n°1552581
masklinn
í dag viðrar vel til loftárása
Posté le 02-05-2007 à 20:18:13  profilanswer
 

MagicBuzz a écrit :

sinon, ton algo, en français, ça donne quoi ? (parcequ'il a l'air un peu différent du mien, mais je pige pas une ligne sur 15 :D


C'est une traduction directe du Crible en Haskell.

 

Je te le détaille dans un thread dédié dans la souscat FP, histoire de cesser le HS

 

edit: http://forum.hardware.fr/hfr/Progr [...] 3972_1.htm


Message édité par masklinn le 02-05-2007 à 20:23:36

---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box by throwing away the limits imposed by overbearing genetic regulations? Isn't that a good thing?
n°1553139
MagicBuzz
Posté le 03-05-2007 à 14:20:00  profilanswer
 

Après correction de mon algo complètement pourri, finalement le crible d'eratosthene est infiniment meilleur que mon approche pourrie :o
 
Et C# défonce haskell (envirnon 5 fois plus rapide... jusqu'à ce qu'on arrive à plus de 10 000 000, là C# n'aime pas les gros tableaux et devient 3 fois plus lent :spamafote:)
 

Code :
  1. Console.WriteLine("Da pas magic solution..." );
  2.            {
  3.                DateTime d1 = DateTime.Now;
  4.                bool[] nbrs = new bool[val + 1];
  5.                int maxi = val + 1;
  6.  
  7.                for (int i = 0; i < maxi; i++)
  8.                {
  9.                    nbrs[i] = true;
  10.                }
  11.  
  12.                for (int i = 2; i < maxi; i++)
  13.                {
  14.                    for (int j = i * 2; j < maxi; j += i)
  15.                    {
  16.                        nbrs[j] = false;
  17.                    }
  18.                }
  19.  
  20.                for (int i = 2; i < maxi; i++)
  21.                {
  22.                    if (nbrs[i])
  23.                    {
  24.                        //Console.WriteLine(i);
  25.                    }
  26.                }
  27.                                
  28.                Console.WriteLine("Temps d'exécution : {0} ms", DateTime.Now.Subtract(d1).TotalMilliseconds);
  29.            }


 
Et qu'on aille pas me dire que c'est du chinois pour ceux qui font du C :o


Message édité par MagicBuzz le 03-05-2007 à 14:23:27
n°1553281
matafan
Posté le 03-05-2007 à 16:22:32  profilanswer
 

Le crible de machin c'est l'algo le plus rapide, point. Le seul inconvénient c'est qu'il n'est exploitable que pour les petits nombres (TRES petits) car extrêmement gourmand en mémoire.

n°1553298
masklinn
í dag viðrar vel til loftárása
Posté le 03-05-2007 à 16:36:23  profilanswer
 

matafan a écrit :

Le crible de machin c'est l'algo le plus rapide, point. Le seul inconvénient c'est qu'il n'est exploitable que pour les petits nombres (TRES petits) car extrêmement gourmand en mémoire.


Je crois que le  crible d'Atkin est normalement plus rapide, mais plus complexe (et c'est ne évolution du crible d'Eratosthène et pas un algo complètement différent)


---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box by throwing away the limits imposed by overbearing genetic regulations? Isn't that a good thing?
n°1553381
Siluro
Posté le 03-05-2007 à 19:21:21  profilanswer
 

lamouche8 a écrit :

Bonjour,
Je dois trouver les nombres premiers de 1 à 100 en C.
Pour ça, j'ai écris les nombres dans un tableau via ce code :

Code :
  1. for(c=0;c<nbc;c++)
  2. }



[:autobot] Ici, ça va de 0 à 99.

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  crible d'Eratosthene en c

 

Sujets relatifs
Plus de sujets relatifs à : crible d'Eratosthene en c


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)