UNIVERSITÉ BORDEAUX I  Département premier cycle Sciences
    Juin 1995
  
  
Polycopié, notes de cours et de TD autorisés.
Autres documents interdits.
Les 3 exercices sont indépendants ; donner des réponses simples et précises : les fonctions C demandées sont très courtes (quelques lignes). Ecrire des généralités, ou copier des fonctions vues en cours ou en TD, vous fera perdre du temps sans vous rapporter aucun point.
  | 
    typedef int nombre [MAX];
  Veiller, dans tous les cas, à la qualité des en-têtes
  de fonctions.
    
Note : ici, comme dans le reste de l'exercice, on ne demande aucune conversion d'une base dans une autre.
Comment proposez-vous de traiter le cas où le nombre de chiffres de x+y dépasse MAX ?
  struct complexe {double reel, imaginaire; };
  et on dispose des fonctions :
struct complexe somme (struct complexe u, struct complexe v); struct complexe produit (struct complexe u, struct complexe v); double module (struct complexe z);Soit f la fonction définie par f(z) = z2+c , où c désigne une constante complexe, et soit zn la suite définie par la récurrence :
  | 
Note : veiller à bien spécifier les paramètres de cette fonction.
  void decompose (long n) {
    long d;
    for (d = 2; d * d <= n;)
      if (n % d == 0) {
        printf (" %d", d);
        n = n / d;
      }
      else d++;
    printf (" %d\n", n);
  }
  Par exemple, si n = 200, cette fonction affiche : 2 2 2 5 5.
Modifier cette fonction pour qu'elle affiche chaque facteur avec sa multiplicité ; par exemple, si n = 200, la fonction modifiée affiche : 2 puissance 3, 5 puissance 2.
  void afficher (nombre x) {
    int i, j;
    
    for (i = MAX - 1; i > 0 && x [i] == 0; i--);
    for (j = i; j >= 0; j--)
      printf ("%d", x [j]);
    printf ("\n");
  }
Variantes et remarques :
void afficher (int *x) ou : void afficher (int x [])
for (; i >= 0; i--) printf ("%d", x [i]);
  void somme (nombre z, nombre x, nombre y, int base) {
    int i, retenue = 0;
    
    for (i = 0; i < MAX; i++) {
      z [i] = x [i] + y [i] + retenue;
      if (z [i] >= base) {
        retenue = 1;
        z [i] = z [i] - base;
      }
      else
        retenue = 0;
    }
  }
Noter que la base est un paramètre de cette fonction, car il est impossible d'additionner x et y sans connaître la base utilisée.
Le nombre de chiffres de x+y dépasse MAX si et seulement si la fonction se termine avec retenue = 1. Le moyen le plus simple de le signaler à l'utilisateur (qui en fera ce qu'il voudra), est de transformer cette fonction en une fonction booléenne : remplacer void par int dans l'en-tête, et ajouter
return retenue;
à la fin (2 points).
Remarque : certains étudiants n'ont pas utilisé de variable retenue , et ont écrit :
    for (i = 0; i < MAX; i++) {
      z [i] = x [i] + y [i] + z [i];
      if (z [i] >= base) {
        z [i + 1] = 1;
        z [i] = z [i] - base;
      }
      else
        z [i + 1] = 0;
    }
    Mais cette solution est fausse pour la première
    et la dernière valeur de i : 
    z [0] n'est pas initialisé, et surtout
    z [MAX] n'existe pas.
  struct complexe f (struct complexe z, struct complexe c) {
    return somme ( produit (z, z), c );
  }
    
  int disque (struct complexe z, struct complexe c,
              int n, double r) {
    int i;
    for (i = 1; i <= n; i++)
      z = f (z, c);
    return ( module (z) <= r );
  }
La variante suivante est évidemment correcte, mais peu élégante :
    if ( module (z) <= r )
      return 1;
    else
      return 0;
  void decompose (long n) {
    long d;
    int multiplicite;
    for (d = 2; d * d <= n; d++) {
      multiplicite = 0;
      while (n % d == 0) {
        multiplicite++;
        n = n / d;
      }
      if (multiplicite > 0)
        printf ("%d puissance %d, ", d, multiplicite);
    }
    if (n > 1)
      printf ("%d", n);
    printf ("\n");
  }
  Ne pas oublier if (multiplicite > 0) avant printf.
  La solution voisine :
  int multiplicite = 0;
  for (d = 2; d * d <= n;) {
    if (n % d == 0) {
      multiplicite++;
      n = n / d;
    }
    else {
      if (multiplicite > 0)
        printf ("%d puissance %d, ", d, multiplicite);
      multiplicite = 0;
      d++;
    }
  }
  a été considérée comme correcte, mais en fait
  elle pose des problèmes délicats quand on sort de la boucle :
  le dernier diviseur d a-t-il bien été affiché,
  et sinon est-il égal à n ?