Des calculs entachés d'erreurs !

Un programme

Vous avez ci-dessous un programme C. Analysez-le, puis exécutez-le.

1
#ifndef REPRESENTATION_DON_H_
2
#define REPRESENTATION_DON_H_
3
#include <stdlib.h>
4
#include <stdio.h>
5
void representation_don(){
6
  float f, f2;
7
  float f3;
8
  int i=0 ;
9
  f=f2=1. ;
10
  do { /* boucle */
11
    ++i;
12
    f2/=10; /* division par 10 */
13
    f3=f+f2 ;
14
  }
15
  while (f!=f3) ;
16
  printf( "i=%d f=%f et f2=%e\n", i, f, f2);
17
}

Question

Le programme est-il correct ? Le résultat est-il celui que vous attendiez ? Pourquoi ?

Indice

Souvenez-vous que la représentation des réels par le type float permet de coder un ensemble fini de valeurs.

Solution

Les conséquences d'une représentation discrète !

L'analyse du code montre que :

  • Après l'initialisation à 1.0 dans une boucle, f2 prend des valeurs successives décroissantes dans un rapport de 10,

  • À chaque étape de la boucle, nous calculons la somme f+f2 que nous mettons dans f3,

  • La fin de la boucle est conditionnée par l'égalité (f==f3) donc f=f+f2.

Résultat attendu :

En logique mathématique, les valeurs successives contenues par f2 sont non nulles, donc la somme f+f2 est différente de f. Le programme doit boucler à l'infini.

L'exécution nous montre qu'il n'en est rien : le programme s'arrête normalement.

Ceci est dû au fait que la représentation des réels est un domaine de valeurs discret avec approximation si nécessaire. Ainsi, lorsque la valeur de f2 est de l'ordre de l'intervalle entre 2 valeurs successives, la représentation du résultat par approximation aboutit à la perte de cette valeur de f2 peu significative au regard de la valeur de f.

Modifiez votre programme en introduisant une autre boucle qui affecte à f2 les mêmes valeurs successives et comparez, à chaque étape, les deux dernières valeurs de f2.

Question

Que constatez-vous à propos de la valeur de i affichée ? Pourquoi ?

Indice

Rappelez-vous que la représentation des réels n'est pas uniforme sur le domaine des réels.

Solution

La valeur de i passe de 8 à 47 (les valeurs peuvent varier en fonction de la machine utilisée). On en conclut que la précision est plus importante vers 0.

Vers 0, l'intervalle de représentation est plus petit, donc la densité des valeurs représentées est plus importante, ce qui réduit les erreurs d'approximation.