IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Turbo Pascal Discussion :

Crible d'Eratosthène (Nombres premiers)


Sujet :

Turbo Pascal

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4
    Points : 8
    Points
    8
    Par défaut Crible d'Eratosthène (Nombres premiers)
    Voici un programme qui effectue le crible d'Eratosthène en Pascal.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    Program Primalite;
    Uses crt;
     
    type tab=array[0..3500] of integer;
     
    function next(A:tab;e,N:integer):integer;
    var f:integer;
    Begin
         f:=e+1;
         while (A[f]=0) and (f<=N) do Begin f:=f+1; end;
         next:=f;
    end;
     
    procedure erato (var B:tab;N:integer);
    var i,j,r,h,t: integer;
         A:tab;
    Begin
         for j:=2 to N do
         Begin
              A[j]:=j;
         end;
         A[1]:=0;
         i:=2;
         r:=i;
         while i<sqrt(N) do
         Begin
              h:=i*r;
              if h<N
                   then
                        Begin
                             A[h]:=0;
                             r:=r+1;
                        end
                   else
                        Begin
                             i:=next(A,i,N);
                             r:=i;
                        end
         end;
         t:=1;
         for i:=2 to N do
         Begin
              if A[i]<>0 then
                             Begin
                                  B[t]:=A[i];
                                  t:=t+1;
                             end
         end;
         t:=t-2;
         B[0]:=t;
    end;
     
    procedure affiche(var B:tab);
    var i:integer;
    Begin
         for i:=0 to B[0] do write(B[i],' ');
    end;
     
    var
         N:integer;
         B:tab;
    Begin
         clrscr;
         write('Donner les nombres premiers inférieurs à ?');
         readln(N);
         erato(B,N);
         affiche(B);
         write('');
         readln(N);
         erato(B,2);
    end.
    Celui ci donne tous les nombres premiers en dessous d'un certain rang. Ici 3500 au maximum. La première case indique le nombre de nombres premiers formés. Le programme peut encore être amélioré mais il fait ce dont j'ai besoin !

    Voici ce que l'on obtient pour N=1000 :


    On a bien le compte, vous pouvez comparer :
    https://fr.wikipedia.org/wiki/Liste_de_nombres_premiers

    Et ci-dessous, mon post initial, avant que je ne finalise le programme.
    Bonsoir,
    je travaille sur un programme qui donnerait tous les nombres premiers en dessous d'un certain rang (ici 1000).
    Je pense pouvoir me débrouiller seul pour l'idée générale du codage mais j'ai un message d'erreur dont je ne sais me débarrasser.
    Quand j'essaie de compiler, le curseur se place sur le e de 'else' ligne 31 et affiche "Error 113: Error in statement.". Ce serait une erreur de Begin et de end mais je ne vois pas vraiment où ...

    Merci d'avance !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    Program Primalite;
    Uses Crt;
     
    type tab=array[1..1000] of integer;
     
    function next(A:tab,e,N:integer):integer;
    var f:integer;
    Begin
         f:=e+1;
         while (A[f]=0) and (f<=N) do Begin f:=f+1; end;
         next:=f;
    end;
     
    procedure erato (var B:tab;N:integer);
    var i,j,r,h,t: integer;
         A:tab;
    Begin
         for j:=2 to N do
         Begin
              A[j]:=j;
         end;
         A[1]:=0;
         i:=2;
         r:=i;
         while i<sqrt(n) do
         Begin
              h:=i*r;
              if h<n
                   then A[h]:=0;
                        r:=next(A,r,N);
                   else i:=next (A,i,N);
         end;
         t:=1;
         for i:=2 to N do
         Begin
              if A[i]<>0 then B[t]:=A[i];
                                   t:=t+1;
         end;
         B[0]:=t;
         erato:=B;
    end;

  2. #2
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 464
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 464
    Points : 4 311
    Points
    4 311
    Par défaut
    Effectivement, si il y a plusieurs instructions dans un bloc, elles doivent être comprises entre un begin...end. Le "Then" du "If" est un de ces blocs:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if h<n then
    begin
      A[h]:=0;
      r:=next(A,r,N);
    end else
      i:=next (A,i,N);
    M.Dlb - Modérateur z/OS - Rédacteur et Modérateur Pascal

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4
    Points : 8
    Points
    8
    Par défaut
    Merci d'une réponse aussi rapide !
    J'avais essayé la même chose mais j'avais mis un ';' après le end, du coup ça ne marchait pas.

    Une dernière chose, pourriez vous me dire comment afficher le tableau formé par la procédure erato ? Je n'arrive jamais à écrire la fin de mes programmes.
    J'ai essayé ça mais j'ai toutes sortes de bugs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Begin
    B:tab; 
    erato(B,1000);
    var i :integer;
    for i:=0 to B[0] do
         writeln(B[i])
    end.
    Le programme donne en B[0] la taille du tableau voulu. Merci !

  4. #4
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 464
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 464
    Points : 4 311
    Points
    4 311
    Par défaut
    Il faut revoir la déclaration des variables dans la programme principal, et mettre un ; à la fin du writeln.
    M.Dlb - Modérateur z/OS - Rédacteur et Modérateur Pascal

  5. #5
    Membre éclairé

    Homme Profil pro
    Rédacteur technique (retraité)
    Inscrit en
    Octobre 2009
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 81
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Rédacteur technique (retraité)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 168
    Points : 807
    Points
    807
    Par défaut Rôle du point-virgule (;) en Pascal
    Bonjour!

    Citation Envoyé par M.Dlb
    Il faut revoir la déclaration des variables dans la programme principal, et mettre un ; à la fin du writeln.
    Inexact en ce qui concerne le ; qui est ici situé juste avant un END.

    En effet, baucoup pensent qu'en Pascal le ; doit être utilisé pour terminer une instruction. En réalité sa fonction est de la séparer de la suivante. Sa présence n'est donc pas logique à la fin de la dernière instruction d'un bloc, cette instruction n'étant suivie d'aucune autre. Les compilateurs considèrent généralement dans ce cas que le bloc se termine sur une intruction "vide".

    Les instructions vides sont autorisées en Pascal et peuvent, avec certains compilateurs, générer une instruction machine NOP (qu'un optimiseur un tant soit peu intelligent pourra éventuellement éliminer!). Essayez de remplacer un unique ; par une série de plusieurs ( ;;;;; ) et vous verrez que le compilateur ne se fâche aucunement

    Cette considération du ; comme un séparateur plutot qu'un terminateur en éclairera peut-être certains sur des comportements du langage jugés jusqu'ici comme incompéhensible. Notamment juste avant ELSE, un ";" considéré comme séparateur implique clairement que la partie THEN comporte au moins deux instructions (dont une vide) alors que selon la règle syntaxique du IF il ne peut y en avoir qu'une, d'où le message d'erreur émis systématiquement dans ce cas.

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4
    Points : 8
    Points
    8
    Par défaut
    J'ai un peu retravaillé dessus. J'arrive à bien le lancer. J'ai des résultats plus ou moins justes mais je devrais pouvoir régler ça, merci !

  7. #7
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Conreik Voir le message
    J'ai des résultats plus ou moins justes mais je devrais pouvoir régler ça, merci !
    Si je puis me permettre, ce serait quand même dommage de laisser la discussion dans cet état, après l'avoir ouverte sous un titre si prometteur : "Crible d'Eratosthène". Je pense aux innocents qu'un moteur de recherche va renvoyer vers cette discussion, et qui n'y trouveront rien, ni une présentation théorique du sujet, ni un algorithme, ni un morceau de code qui fonctionne.

    Pour le moment, le titre qui conviendrait, c'est : "Comment déclarer une variable en Pascal".
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4
    Points : 8
    Points
    8
    Par défaut
    D'accord, quand le programme marche parfaitement, je le posterai.

    EDIT : C'est fait ! J'ai édité mon premier post, pour que quelqu'un qui le cherche le trouve facilement. Encore merci

  9. #9
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 552
    Points : 3 918
    Points
    3 918
    Par défaut
    Salut

    Pour gagner de la mémoire, transforme ton type tableau en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    type tab=array[0..3500] of boolean;
    car ta structure est redondante (on a tab[i]=i), tu affectes True si le nombre est premier. Tu n'as plus qu'à conserver un seul tableau, cela t'évite de recopier laborieusement, en le compressant, le tableau A dans le tableau B.

    pour l'affichage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    procedure affiche(const B:tab);
    var
      i:integer;
    begin
      for i:=Low(B) to High(B) do
        if B[i] then
          write(i, ' ');
    end;
    Dans ta procédure erato, calcule une fois pour toutes sqrt(N) et ne le réévalues pas à chaque fois dans la condition du while, c'est un calcul coûteux.

    Il y a eu récemment un fil de discussion sur ce sujet (en fait sur les nombres jumeaux).

    @+

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

Discussions similaires

  1. Réponses: 24
    Dernier message: 27/09/2005, 21h16
  2. [défi n°8]: premiers nombres premiers
    Par javatwister dans le forum Général JavaScript
    Réponses: 41
    Dernier message: 14/06/2005, 10h22
  3. [LG]Calcul des 15 premiers nombres premiers
    Par yffick dans le forum Langage
    Réponses: 12
    Dernier message: 18/09/2004, 14h57
  4. Cripter avec des nombres premiers
    Par clovis dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 14/04/2004, 19h10
  5. premier nombre premier superieur à m=10^100+1
    Par azman0101 dans le forum Mathématiques
    Réponses: 4
    Dernier message: 17/04/2003, 03h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo