Raffinages successifs

Il est souvent difficile d'écrire la version définitive du premier coup, on risque en effet de se perdre dans des détails et de ne pas voir l'essentiel.

Pour éviter cet écueil, on procède par étapes en définissant des actions très générales (qui ne sont pas des actions élémentaires de la machine).

Pour passer d'une étape (version) à l'étape suivante , on détaille un peu plus les actions générales, mais pour ne pas perdre l'évolution de ce processus, on place l'action générale en commentaire, et on la détaille un peu plus à la suite de ce commentaire.

A la fin on doit obtenir une version qui ne contient plus que des actions exécutables par l'opérateur.

Cette méthode est appelée méthode par "raffinages successifs".

Cette méthode donne de bons résultats, mais elle ne garantit pas qu'on obtiendra bien le résultat (parfois il faut revenir en arrière).

Un programme est un enchaînement de différentes opérations et calculs plus ou moins complexes. La difficulté pour élaborer un tel programme est généralement proportionnelle à la taille du problème.

On part d'une description de la résolution du problème, très abstraite et à chaque étape, on la raffine en utilisant :

  • les structures de contrôle pour décrire les choix et les répétitions.

  • les structures de composition pour élaborer un calcul complexe à partir de calculs plus élémentaires (composition fonctionnelle et séquentielle)jusqu'à obtenir quelque chose écrit dans un langage proche de celui de la machine.

Il ne restera alors qu'à traduire dans le langage de programmation utilisé.

Le raffinage consiste en ces trois étapes où se mêlent rigueur et savoir-faire :

  • Diviser le problème à résoudre en sous-problèmes. C'est une partie importante qui conditionne le reste et qui, malheureusement, n'est basée que sur l'expérience.

  • Résoudre chacun des sous-problèmes soit en appliquant à nouveau la première étape, soit en résolvant directement le sous-problème qui est un problème simple et connu.

  • Combiner les résultats des sous-problèmes. C'est la partie la plus rigoureuse dans laquelle on doit faire attention à ce que donnent les sous-résultats et à ce qu'il est nécessaire de faire pour obtenir le résultat final

La recopie

Objectif : Permuter 2 variables (A et B )

Niveau 1 : Idée Générale

debut /* niveau 1 */

Recopier A dans C;

Recopier B dans A;

Recopier C dans B;

fin

Remarque : on passe par une recopie dans une autre variable C pour conserver la valeur de A avant de faire la copie de B.

Niveau 2 : On détaille un peu plus les actions qui devront être décomposées vue le peu d'opérations élémentaires au niveau de l'affectation

debut /* niveau 2 */

/* Recopier A dans C; */

Mise à zéro de C;

Tant que A > 0 Faire

  Debut

  Incrémenter C de 1;

  Décrémenter A de 1;

fin /*du Tant que */

Et ...

/* Recopier B dans A; */

Tant que B > 0 Faire

  Debut

    Incrémenter A de 1;

    Décrémenter B de 1;

  fin /* du Tant que */

/* Recopier C dans B; */

...

Niveau 3 : il n'y a plus d'opérations complexes, on traduit toutes les opérations avec les opérations de base et on combine les 2 parties.

Debut /* niveau 3 */

  /* Recopier A dans C; */

  C<-0;

  Tant que A > 0 Faire

  Debut

    C<-C+1;

    A<-A-1;

  fin /*du Tant que */

  /* Recopier B dans A; */

  Tant que B > 0 Faire

  Debut

    A<-A+1;

    B<-B-1;

  fin /* du Tant que */

  /* Recopier C dans B; */

  ...

Fin

Objectif : Écrire un programme qui lit un certain nombre d'entiers et détermine si chacun d'eux est pair, et qui, dans le cas contraire, détermine si l'entier est premier. (L'utilisateur rentrera les nombres un à un et tapera 0 pour terminer sa saisie.)

Niveau 0

Debut /* niveau 0 */

  Lire et étudier une liste d'entiers

Fin

Pour passer au niveau 1 :

  • Je reprends l'action et je raffine.

  • Tout en raffinant, je fais des choix de conception de l'algorithme : Mémorise-t-on toutes les valeurs ou les traite-t-on au fur et à mesure ? Est-on limité en taille mémoire ? Comment se fait la saisie ? (0 = arrêt ou nombre d'entiers connu ?)

Niveau 1

Début /* niveau 1 */

  /* Programme qui lit et étudie une liste d'entiers */

  Lire un entier ; /* (a) */

  Tant que cet entier est différent de 0 Faire /* (b) */

  Début

      Calculer s'il est pair et éventuellement s'il est premier ; /* (c) */

      Lire l'entier suivant /* (d) */

  fin

Fin

Ici, les actions a, b et d sont suffisamment simple pour qu'on puisse les traiter à chaque niveau dans son intégralité, mais l'action c nécessite un nouveau niveau. Chaque opération ou calcul d'un niveau est indépendamment des autres. Il faut simplement s'assurer que l'état initial et l'état final de l'opération raffinée sont bien ceux attendus.

Début /* niveau 2 */

  /* Programme qui lit et étudie une liste d'entiers */

  /* Lire un entier */

  Lire (N);

  Tant que /* cet entier est différent de 0 */ N ≠ 0 Faire

  Début

    /*Calculer s'il est pair et éventuellement s'il est premier*/

    S'il est pair alors

    Début

      Afficher un message 1;

    Sinon

      Afficher un message 2;

      Calculer s'il est premier ;

      Afficher un message selon qu'il soit premier ou non

    fin ;

  /*Lire l'entier suivant*/

  Lire (N)

  fin

Fin.

Niveau 3

Début /* niveau 3 */

  /* Programme qui lit et étudie une liste d'entiers */

  /* Lire un entier */

  Lire (N);

  Tant que /* cet entier est différent de 0 */ N ≠ 0 Faire

  Début

    /* Calculer s'il est pair et éventuellement s'il est premier */

    Si /*il est pair*/ (N mod 2) = 0 alors

    début

      /* Afficher un message */

      Afficher (N, '' est pair'');

    Sinon

      /* Afficher un message */

      Afficher (N, '‘ n'est pas pair'');

      /* Calculer s'il est premier */

      Diviseur <- 2;

      Tant que ((N mod Diviseur) ≠ 0) et (Diviseur * Diviseur ≤ N) Faire

      début

        Incrémenter le Diviseur ;

        /* Afficher un message selon qu'il soit premier ou non */

        Si {s'il est premier} N mod Diviseur ≠ 0 alors

        début

          Afficher un message

        Sinon

          Afficher un message

        fin ;

        /* Lire l'entier suivant */

      fin

    fin

    Lire (N)

  fin

Fin.

Niveau 4

Début /* niveau 4 */

  /* Programme qui lit et étudie une liste d'entiers */

  /* Lire un entier */

  Lire (N);

  Tant que /* cet entier est différent de 0 */ N ≠ 0 Faire

  début

    /* Calculer s'il est pair et éventuellement s'il est premier*/

    Si {il est pair} (N mod 2) = 0 alors

    début

      /*Afficher un message*/

      Afficher (N, "est pair")

    Sinon

      /*Afficher un message*/

      Afficher (N, '' n'est pas pair'');

      /*Calculer s'il est premier*/

      Diviseur <- 2;

      Tant que ((N mod Diviseur) ≠ 0) et (Diviseur * Diviseur ≤ N) Faire

        début

        /*Incrémenter le Diviseur*/

        Diviseur <- Diviseur + 1;

        /*Afficher un message selon qu'il soit premier ou non*/

        Si {s'il est premier} N mod Diviseur ≠ 0 alors

          début

          /*Afficher un message*/

          Afficher (N, '' est premier'')

          fin

        Sinon

          début

          /*Afficher un message*/

          Afficher (N, '' n'est pas premier'')

          fin

        fin

    fin

  /*Lire l'entier suivant*/

    Lire (N)

  fin

Fin.

La conception d'un algorithme par raffinage ne garantit pas qu'il n'y a pas d'erreurs

Pensez à vérifier :

  • Que des variables utilisées dans la condition d'une sélection ont bien été associées à une valeur avant l'évaluation de la condition.

  • Que l'expression évaluée dans la condition d'une répétition évolue bien et va converger vers un arrêt.

  • Que vous avez bien traité toutes les opérations du niveau précédent.

AccueilAlgorithmique > Raffinages successifs< PrécédentSuivant >