UNIVERSITÉ BORDEAUX I  Département premier cycle Sciences
    Janvier 1995
  
  
Notes de cours et de TD autorisées. Autres documents interdits.
Les 3 exercices sont indépendants ; donnez 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.
  | 
  | 
Ecrire, en langage C, la fonction integrale , qui effectue ce calcul approché ; on suppose la fonction f écrite par ailleurs. Veiller à spécifier au mieux les paramètres.
Une meilleure approximation est obtenue en remplaçant f, sur [xi xi+1], par la fonction constante égale à :
  | 
  | ||||||||||||||||||||||
  #define MAX 20
  
  void f (int *t, int *u, int n) {
    int i, j;
    
    for (j = 0; j <= MAX; j++)
      u [j] = 0;
    for (i = 0; i < n; i++) {
      j = t [i];
      u [j]++;
    }
  }
  
  On suppose donné un tableau notes, contenant les dix valeurs
  suivantes :
  
  | 
f (notes, a, 10) ?
Que calcule, de façon générale, la fonction f ?
Cette fonction comporte une instruction dangereuse : laquelle ? Que faudrait-il ajouter pour rendre cette fonction sûre ?
  | 
  | 
double integrale (double a, double b, int n) {
  int i;
  double x = a, delta = (b - a) / n, s = 0;
  
  for (i = 0; i < n; i++) {
    s = s + f (x);
    x = x + delta;
  }
  return s * delta;
}
De nombreuses variantes sont possibles, par exemple, sans utiliser de variable x (mais au prix de multiplications supplémentaires) :
  for (i = 0; i < n; i++)
    s = s + f (a + i * delta);
La seconde méthode de calcul (plus précise) consiste à remplacer :
  | 
double integrale (double a, double b, int n) {
  int i;
  double x = a, delta = (b - a) / n, s = ( f(a) + f(b) ) / 2;
  
  for (i = 1; i < n; i++) {
    x = x + delta;
    s = s + f (x);
  }
  return s * delta;
}
Si on ne remarque pas la simplification ci-dessus, on peut écrire aussi, pour éviter de calculer inutilement deux fois f à chaque itération :
  double
    x = a, delta = (b - a) / n,
    s = 0, u = f (a), v;
  
  for (i = 0; i < n; i++) {
    x = x + delta;
    v = f (x);
    s = s + (u + v) / 2;
    u = v;
  }
  | 
void suite (long *u, int n) {
  int i, j;
  
  u [0] = 1;
  for (i = 1; i <= n; i++) {
    u [i] = 0;
    for (j = 0; j < i; j++)
      u [i] = u [i] + u [j] * u [i - j - 1];
  }
}
Evidemment, la solution suivante est équivalente :
  for (i = 0; i < n; i++) {
    u [i + 1] = 0;
    for (j = 0; j <= i; j++)
      u [i + 1] = u [i + 1] + u [j] * u [i - j];
  }
  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
La fonction f enregistre, dans le tableau u, le nombre d'occurrences de chaque note dans le tableau t (par exemple pour préparer un histogramme).
L'instruction dangereuse est j = t [i]; u [j]++ , car elle suppose que le tableau t ne contient que des entiers entre 0 et 20 ; des fautes de saisie peuvent alors entraîner un comportement dangereux (ou un "plantage") du programme. Il est conseillé d'écrire plutôt :
  j = t [i];
  if (j >= 0 && j <= MAX)
    u [j]++;