crible d'Eratosthene en c

crible d'Eratosthene en c - C - Programmation

Marsh Posté le 02-05-2007 à 15:42:47    

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.

Reply

Marsh Posté le 02-05-2007 à 15:42:47   

Reply

Marsh Posté le 02-05-2007 à 15:47:35    

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
Reply

Marsh Posté le 02-05-2007 à 15:54:44    

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
Reply

Marsh Posté le 02-05-2007 à 15:57:04    

Reply

Marsh Posté le 02-05-2007 à 16:13:32    

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
Reply

Marsh Posté le 02-05-2007 à 16:17:10    

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

Reply

Marsh Posté le 02-05-2007 à 16:17:50    

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
Reply

Marsh Posté le 02-05-2007 à 16:22:54    

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 ;)

Reply

Marsh Posté le 02-05-2007 à 16:27:56    

ah bah ok lol alors hein ;)


---------------
Töp of the plöp
Reply

Marsh Posté le 02-05-2007 à 16:32:30    

Reply

Marsh Posté le 02-05-2007 à 16:32:30   

Reply

Marsh Posté le 02-05-2007 à 16:35:59    

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

Reply

Marsh Posté le 02-05-2007 à 16:42:49    

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...

Reply

Marsh Posté le 02-05-2007 à 17:42:45    

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
Reply

Marsh Posté le 02-05-2007 à 18:04:40    

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
Reply

Marsh Posté le 02-05-2007 à 18:38:40    

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

Reply

Marsh Posté le 02-05-2007 à 18:49:57    

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

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-05-2007 à 20:06:41    

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]

Reply

Marsh Posté le 02-05-2007 à 20:09:12    

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]

Reply

Marsh Posté le 02-05-2007 à 20:10:22    

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

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-05-2007 à 20:14:01    

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

Reply

Marsh Posté le 02-05-2007 à 20:14:27    

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

Reply

Marsh Posté le 02-05-2007 à 20:16:42    

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

Reply

Marsh Posté le 02-05-2007 à 20:18:13    

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

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 03-05-2007 à 14:20:00    

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
Reply

Marsh Posté le 03-05-2007 à 16:22:32    

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.

Reply

Marsh Posté le 03-05-2007 à 16:36:23    

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)


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 03-05-2007 à 19:21:21    

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.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed