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

Autres IDE Pascal Discussion :

Compilation correcte, problème de logique


Sujet :

Autres IDE Pascal

  1. #1
    Nouveau membre du Club
    Inscrit en
    Août 2009
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 69
    Points : 35
    Points
    35
    Par défaut Compilation correcte, problème de logique


    Exercice 1 : Tester la primalité d'un entier naturel.

    A partir de l'algorithme ci-dessous :
    Code Algo : 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
    Algorithme TestPrimalite
    Var nbre, diviseur : entier
    Début
        Répéter
             écrire "donnez le nombre à tester : "
             lire(nbre)
        Jusqu'à (nbre > 2) 
        diviseur ← 2
        TantQue (nbre mod diviseur <> 0) et (diviseur <= racine(nbre)) Faire     
             diviseur ← diviseur + 1
        FinTantQue
        Si (nbre mod diviseur <> 0)
        Alors écrire nbre, "est un nombre premier"
        Sinon écrire nbre, "n'est pas un nombre premier" 
        FinSi
    Fin

    J'obtiens le programme Pascal écrit sous Dev-Pascal.
    Il atteint l'objectif. Vous pouvez l'exécuter (faites un copier-coller) :
    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
    Program TestPrimalite (input, output);
    Uses crt;
    Var nombre, diviseur : integer;
        rep : char;
    BEGIN
     repeat
     clrscr;
     writeln ('               --------------------------------------------');
     writeln ('               |      TEST DE PRIMALITE D''UN NOMBRE       |' );
     writeln ('               --------------------------------------------');
     repeat
     writeln;
     writeln ('0 Et 1 Ne Sont Pas Des Nombres Premiers');
     writeln ('2 Est Un Nombre Premier');
     writeln;
     write('Donnez Un Entier Strictement Superieur A 2 : ');
     readln(nombre);
     until (nombre>2);
     diviseur := 2;
     writeln;
     while (((nombre mod diviseur)<> 0)and(diviseur <= sqrt(nombre))) do
            inc(diviseur, 1);
     if (nombre mod diviseur <> 0)
     then writeln (nombre, ' Est Un Nombre Premier')
     else writeln (nombre, ' N''est Pas Un Nombre Premier');
     writeln;
     write ('Voulez-Vous Tester Un Autre Nombre (O(Oui)/N(Non)) ? : ');
     readln(rep);
     until (rep = 'N')or(rep = 'n');
    END.
    Exercice 2 : Déterminer les nombres premiers d'un intervalle donné, les bornes de l'intervalle étant définies par l'utilisateur.

    Mon idée est la suivante : en parcourant l'intervalle de sa borne inférieure à sa borne supérieure, on teste chacun de ses nombres selon l'algorithme defini plus haut. si le nombre est premier, on l'affiche, sinon on passe au suivant.

    Mon problème : D'où le programme ci-dessous. La compilation ne revèle aucune erreur de syntaxe ou autre. Mais le programme fournit un résultat erroné.
    En effet, par exemple , pour l'intervalle [3; 10], il founit 3; 5; 7; 8 et 10 au lieu de fournir les nombres 3; 5 et 7.

    Je pense qu'il s'agit alors d'un problème de logique algorithmique.
    Je tourne en rond. C'est le charme de l'Algorithmique et de la Programmation.
    Veuillez m'aider.

    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
    Program NombresPremiersIntervalle (input, output);
    Uses crt;
    Var borninf, bornsup, i, d : integer;
        rep : char;
    BEGIN
     repeat
     clrscr;
     writeln ('            ------------------------------------------------------');
     writeln ('            | RECHERCHE DE NOMBRES PREMIERS DANS UN INTERVALLE   |' );
     writeln ('            ------------------------------------------------------');
     writeln;
     writeln ('                  Definissez Votre Intervalle de Recherche');
     writeln;
     repeat
     write('Borne Inferieure (Entier Superieur ou Egal A 2) : ');
     readln(borninf);
     until (borninf >= 2);
     writeln;
     repeat
     write('Borne Superieure                                : ');
     readln(bornsup);
     until (bornsup >= borninf);
     d := 2;
     for i:= borninf to bornsup do
          begin
             while (((i mod d)<> 0)and(d <= sqrt(i))) do
                   inc(d, 1); 
             if (i mod d <> 0)
             then writeln(i);
          end;
     writeln;
     write ('Voulez-Vous Tester Un Autre Intervalle (O(Oui)/N(Non)) ? : ');
     readln(rep);
     until (rep = 'N')or(rep = 'n');
    END.

  2. #2
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 938
    Points : 59 416
    Points
    59 416
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    C'est tout simple : il faut faire rentrer l'instruction
    au début de la boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     for i:= borninf to bornsup do
    et ça fonctionnera.

    Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     for i:= borninf to bornsup do
          begin
             d := 2;
             while (((i mod d)<> 0)and(d <= sqrt(i))) do
                   inc(d, 1); 
             if (i mod d <> 0)
             then writeln(i);
          end;
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  3. #3
    Rédacteur
    Avatar de darrylsite
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 299
    Points : 2 501
    Points
    2 501
    Par défaut
    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
     
    function isPrime(nombre: integer) : boolean;
    Var diviseur : integer;
        premier : boolean;
    BEGIN
     if (nombre=1) or (nombre=2) then
      premier:=false
     else
     begin
     diviseur := 2;
     premier :=true;
     while (premier) and(diviseur <= sqrt(nombre)) do
     begin
      if (nombre mod diviseur)= 0 then
       premier:=false
      else
       inc(diviseur);
     end;
    end;
     isPrime:= premier;
    end;
    ensuite
    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
     
    Program NombresPremiersIntervalle (input, output);
    Uses crt;
    Var borninf, bornsup, i : integer;
        rep : char;
    BEGIN
     repeat
     clrscr;
     writeln ('            ------------------------------------------------------');
     writeln ('            | RECHERCHE DE NOMBRES PREMIERS DANS UN INTERVALLE   |' );
     writeln ('            ------------------------------------------------------');
     writeln;
     writeln ('                  Definissez Votre Intervalle de Recherche');
     writeln;
     repeat
     write('Borne Inferieure (Entier Superieur ou Egal A 2) : ');
     readln(borninf);
     until (borninf >= 2);
     writeln;
     repeat
     write('Borne Superieure                                : ');
     readln(bornsup);
     until (bornsup >= borninf);
     
     for i:= borninf to bornsup do
        if isPrime(i) then
         writeln(i);
     
     writeln;
     write ('Voulez-Vous Tester Un Autre Intervalle (O(Oui)/N(Non)) ? : ');
     readln(rep);
     until (rep = 'N')or(rep = 'n');
    END.

  4. #4
    Nouveau membre du Club
    Inscrit en
    Août 2009
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 69
    Points : 35
    Points
    35
    Par défaut It works ! (ça marche)


    J'ai fait comme vous m'avez recommandé, et ça marche.
    Merci beaucoup.

    Que pensez-vous de ma façon d'écrire mes algorithmes et ma façon d'écrire mon code ?
    Que me conseillez-vous pour m'améliorer ou pour me rendre plus performant ?

  5. #5
    Nouveau membre du Club
    Inscrit en
    Août 2009
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 69
    Points : 35
    Points
    35
    Par défaut Deuxième solution aussi Ok, mais erreur de syntaxe !


    La deuxième solution (celle proposée par darrysite) aussi marche. Mais il faut avoir au préalable corrige l'erreur de syntaxe contenue dans le code de la fonction IsPrime.
    Il s'agit de WHILE ... DO.

    En fait, l'utilisation d'une fonction ou d'une procédure est certes judicieuse mais est une autre piste.
    Et à ce sujet, j'ai écrit une fonction ne mettant pas en oeuvre une variable de type booléen.
    Toutefois, je retiens la proposition.

    Merci beaucoup !

  6. #6
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    j'avais fait une routine à l'époque pour trouver tout les diviseurs d'un nombre qui renvois également si le nombre à tester est ou pas un nombre premier :

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    { GetDivisors requirement ----- START }
    type
      pLongintArray = ^TLongintArray;
      TLongintArray = array[0..3999] of Longint;
      { il n'existe logiquement pas de nombre entiers signé 32bits capable de remplir ce tableau
        theoriquement un nombre qui en serait capable serait superieur a 2 milliard.
      }
     
    procedure IDivMod(const Dividend, Divisor: Longint; var Result, Remainder: Longint); register;
    asm
      push ebx;
      mov ebx, edx;
      cdq;
      idiv ebx;
      mov ebx, Remainder;
      mov [ecx],eax;
      mov [ebx],edx;
      pop ebx;
    end;
     
    { GetDivisors requirement ----- END }
     
    { GetDivisors
     
      Renvois les diviseurs existant pour un nombre donné et precise si ce nombre
      est un nombre premier ou pas.
     
      parametres :
        Number        [I] longint, le nombre dont ont veux les diviseurs
        pDivisors     [I] pLongintArray, pointeur sur un tableau de type TLongintArray
        DivisorsCount [O] longint, nombre de diviseurs trouvé et stocké dans pDivisors
        AsPrime       [O] boolean, true si Number est un nombre premier sinon false
     
    }
    procedure GetDivisors(const Number: Longint; const pDivisors: pLongintArray;
              out DivisorsCount: Longint; out AsPrime: boolean);
    var DivisorA, DivisorB, Modulo : Longint;
    begin
      // init
      AsPrime       := false;  // puisque les nombres premiers sont plus rare que les autres
      DivisorA      := 1;      // le premier "plus petit diviseur" connus de Number
      DivisorB      := Number; // le premier "plus grand diviseur" connus de Number
      Modulo        := 0;      // tout nombre % 1 = 0
      DivisorsCount := 0;      // aucuns pour l'instant
     
      if DivisorA <= DivisorB then
        repeat
          { tant que DivisorA inferieur ou egal a DivisorB, cette condition nous permet
            de sortir trés rapidement de la boucle en ne testant que ce qu'il faut pour
            trouver tout les diviseurs de Number.
            * exemple d'iteration avec Number = 10 :
              iterations | diviseurs trouvés | DivisorA | DivisorB | valides | sortie
              1          | 1, 10             | 1        | 10       | oui     | non
              2          | 1, 10, 2, 5       | 2        | 5        | oui     | non
              3          | 1, 10, 2, 5       | 3        | 3        | non     | oui (while a <= B)
     
            * exemple d'iteration avec Number = 11 (nombre premier) :
              iterations | diviseurs trouvés | DivisorA | DivisorB | valides | sortie
              1          | 1, 11             | 1        | 11       | oui     | non
              2          | 1, 11             | 2        | 5        | non     | non
              3          | 1, 11             | 3        | 3        | non     | oui (while a <= b )
     
            * exemple d'iteration avec Number = 25 :
              iterations | diviseurs trouvés | DivisorA | DivisorB | valides | sortie
              1          | 1, 25             | 1        | 25       | oui     | non
              2          | 1, 25             | 2        | 12       | non     | non
              3          | 1, 25             | 3        | 8        | non     | non
              4          | 1, 25             | 4        | 6        | non     | non
              5          | 1, 25, 5          | 5        | 5        | oui     | oui (if a >= b)
          }
     
          { modulo = 0 : si on as un diviseurs valide sous la mains ...
          }
          if Modulo = 0 then
          begin
            { on stocke DivisorA
            }
            pDivisors^[DivisorsCount] := DivisorA;
     
            { on incremente le compteur d'entrées, pas de inc pour eviter un call lent et inutile
              le compilo vas directement nous generer une belle incrementation rapide en assembleur :)
     
              * Comme BruNews a pus me le demontrer, en C ces deux lignes pourrait etre beaucoup plus simple
              si Delphi possedait l'operateur ++ et -- ce qui serait le minimum quand même! (>_<) *
            }
            inc(DivisorsCount);
     
            { test si DivisorA est superieur ou egal a DivisorB, permet la sortie prematurée
              de la boucle pour :
              1) ne pas stocker DivisorB car deja present dans pDivisors (grace aux valeurs
                 precedentes de DivisorA)
              2) eviter des appels, calculs et jump conditionnel inutiles puisqu'on sait que si
                 on arrive ici il ne nous reste plus qu'a determiner si Number est un nombre premier.
                 donc pas besoin d'aller au test DivisorA <= DivisorB, l'un ne peu fonctionner sans
                 l'autre pour garder des performances irreprochable dans tout les cas de figure.
            }
            if DivisorA >= DivisorB then
              Break;
     
            { Stocke DivisorB puisque apparement il est toujours superieur a DivisorB
            }
            pDivisors^[DivisorsCount] := DivisorB;
     
            inc(DivisorsCount);
          end;
     
          inc(DivisorA);
     
          { HAHA! une astuce de phoque, on calcul directement la division et le modulo
            grace aux fonctions de l'unité ExtMath!
            ça nous permet de diviser le temps et les cycles pris par la fonction par 2,
            a l'instar de la fonction SinCos dans les calculs de courbes par exemple...
          }
          IDivMod(Number, DivisorA, DivisorB, Modulo);
        until DivisorA >= DivisorB;
     
      { il nous reste plus grand chose a faire pour determiner que Number est un nombre premier
     
        rappel :
          un nombre premier est un nombre qui ne peut etre divisé que par 1 et par lui même.
     
        nombre premier de 1 a 100 :
          2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97.
      }
      AsPrime := (DivisorsCount = 2) and ((pDivisors^[0] = 1) and (pDivisors^[1] = Number));
    end;
    performance :

    Burn test value : 864864000 :: 1152 divisors!
    1666 cycles
    0.000 secondes
    sur Windows XP Pro SP2, Intel Core2Duo E6300@1.8Ghz, 2Go DDR-2 PC 667
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

Discussions similaires

  1. Problème de logique :)
    Par deaven dans le forum Oracle
    Réponses: 1
    Dernier message: 13/10/2006, 18h49
  2. compilation correcte mais fenetre d'erreur
    Par alibas dans le forum Visual C++
    Réponses: 6
    Dernier message: 01/10/2006, 23h02
  3. [compilation][classpath] problème de classpath
    Par mavina dans le forum Langage
    Réponses: 7
    Dernier message: 28/07/2006, 10h57
  4. Réponses: 10
    Dernier message: 14/07/2006, 20h22
  5. Petit problème de logique...
    Par insomniak dans le forum C++
    Réponses: 15
    Dernier message: 31/10/2005, 20h13

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