Comparaison des réels

Discutez d'informatique ici !
Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

Comparaison des réels

par Dlzlogic » 01 Nov 2012, 14:58

Bonjour,
Un sujet souvent évoqué et qui mérite l'attention.
En informatique, les nombres à virgule flottante, float sur 32 bits, double sur 64 bits et long_double sur 80 bits ont un nombre fini de valeurs possibles.
La précision est de 7 chiffres pour des float, 15 chiffres pour des double et 19 chiffes pour les long_double.
Il en résulte que des réels, mathématiquement égaux, mais résultant d'opérations arithmétiques successives ne seront généralement pas égaux.
Pour le montrer, j'ai fait la simulation suivante répétée 100 fois.
Soit 2 segments AB et CD. Leur intersection est I. Les coordonnées ont été choisies de façon à avoir une intersection franche et ainsi éviter des problèmes relatifs à la précision.
Le programme calcule la projection du point I sur les 2 segments il en résulte les coordonnées d'un point H sur chaque segment. Mathématiquement les coordonnées de H sont identique à celles de I. L'impression le confirme, pourtant la différence de ces 2 valeurs n'est pas nulle.
Pour les 6 premiers essais, le programme imprime les dx du point H et du point I pour chaque segment, puis les dy. Ligne suivante, la différence multipliée par E^10.
On constate que aucune valeur n'est exacte.
On remarquera par ailleurs que, bien que tous les calculs soient faite en "double" le 7è chiffre est parfois différent.


Code: Tout sélectionner
12.430280 12.430280  et 3.486074 3.486074
dX=-2288.020138e-10  dY=8158.384994e-10
16.834583 16.834583  et -16.401022 -16.401022
dX=-894.962184e-10  dY=-918.620522e-10

7.125328 7.125328  et 4.636772 4.636772
dX=941.345810e-10  dY=-1446.566102e-10
13.268119 13.268119  et -22.455408 -22.455408
dX=-1890.511925e-10  dY=-1117.037698e-10

14.613280 14.613281  et 7.035599 7.035598
dX=-2254.128191e-10  dY=4681.934094e-10
17.814513 17.814513  et -14.488207 -14.488207
dX=3749.991961e-10  dY=4610.941744e-10

14.121838 14.121837  et 10.282125 10.282125
dX=3183.644637e-10  dY=-4372.531137e-10
16.859708 16.859708  et -14.892975 -14.892975
dX=2893.464313e-10  dY=3275.568616e-10

17.902688 17.902688  et 17.069322 17.069322
dX=1197.247492e-10  dY=-1255.700077e-10
20.904727 20.904727  et -10.476822 -10.476821
dX=-3208.671515e-10  dY=-6402.362054e-10

19.586919 19.586919  et 4.667658 4.667657
dX=-1443.283004e-10  dY=6056.457371e-10
12.571592 12.571592  et -19.203598 -19.203598
dX=4864.059662e-10  dY=3184.245578e-10

Nombre de bons = 0  nombre de faux = 200



Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

par Dlzlogic » 01 Nov 2012, 15:44

Information complémentaire.
Les données de base, c'est à dire les coordonnées des 4 points étaient en vulgaire float, il en résulte que les calculs étaient réalisés, en fait, en vulgaire float.
Modification faite, le résultat est le suivant :
Code: Tout sélectionner
Nombre de bons = 76  nombre de faux = 124

Anonyme

par Anonyme » 01 Nov 2012, 16:36

@Dlzlogic

Un nombre irrationnel ( donc un nombre réel de l'ensemble noté ) est par définition un nombre dont on ne peut donner qu'une approximation à 10-n près
Donc je ne vois pas trop ce que tu essaies d'expliquer via le codage informatique sur ces nombres ?
(ou sur d'autre nombres car pour moi le format "floating point" est un nombre codé sous une forme appelée en mathématique "forme scientifique")


ps)
je suis peut être passé complètement à coté de l'objectif de cette discussion.
Et si c'est les cas , cela m'intéresserait que tu mettes "des points sur les i"

c'est à dire que tu expliques un peu plus dans le détail l'objectif de la discussion
A+

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 01 Nov 2012, 17:01

Il en résulte que des réels, mathématiquement égaux, mais résultant d'opérations arithmétiques successives ne seront généralement pas égaux.

ya pas besoin de faire une simulation....
Code: Tout sélectionner
#include
int main()
{
  float myFloat=0.3;
  float s=0;
  for(size_t i=0;i<5000;++i){
    s+=myFloat;
  }
  std::cout<<s<<std::endl;
}

la vie est une fête :)

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

par Dlzlogic » 01 Nov 2012, 18:14

ptitnoir a écrit:@Dlzlogic

Un nombre irrationnel ( donc un nombre réel de l'ensemble noté ) est par définition un nombre dont on ne peut donner qu'une approximation à 10-n près
Donc je ne vois pas trop ce que tu essaies d'expliquer via le codage informatique sur ces nombres ?
(ou sur d'autre nombres car pour moi le format "floating point" est un nombre codé sous une forme appelée en mathématique "forme scientifique")


ps)
je suis peut être passé complètement à coté de l'objectif de cette discussion.
Et si c'est les cas , cela m'intéresserait que tu mettes "des points sur les i"

c'est à dire que tu expliques un peu plus dans le détail l'objectif de la discussion
A+
L'objectif de la discussion est qu'en matière générale et en particulier en informatique, cela n'a pas beaucoup de sens de dire que 2 nombres réels sont égaux.
L'explication avec le codage est dans un but de démonstration. Cela fait l'objet d'un long exposé, très technique, mais je n'ai plus les références.
Pour l'utilisateur, ce qu'il faut savoir, c'est qu'une comparaison avec le signe"=" n'a pas beaucoup de sens quand il s'agit de réels, sauf cas particuliers où la valeur du nombre réel a été fixée comme telle et non calculée.
Il est naturellement facile de trouver des contre-exemples, et ça peut satisfaire certains.
Cet exposé citait un cas piège particulièrement dangereux.
Soit l'opération "machin = truc/(a-b)"
il est bien évident que l'on va tester le dénominateur pour s'assurer qu'il n'est pas nul. Il y a 2 façon de le faire :
soit a != b
soit (a-b) != 0
La première expression est casse-cou. La seconde est la bonne méthode.
Il est bien évident que dans l'exemple cité dans le message de 18h01 heure locale, ajouter 5000 fois 0.3 donnera 150. En fait l'opération est l'ajout de 5000 fois la mantisse, c'est à dire 3 et la caractéristique est -1. Libre à chacun de comparer l'égalité de nombre réels, mais il vaut mieux se limier à des applications avec très peu de calculs, surtout pas de graphique, de CAO-DAO etc.

Donc dans la pratique, il faut faire des choses du genre "if (fabs(a-b) > epsilon) ..."

Cas ou le signe "=" est normal.
J'imagine que j'ai une liste de nombre réel résultant de calculs divers. Dans certains cas, pour une raison quelconque, si le calcul donne un résultat inacceptable, alors je lui donne un "code" par exemple 4807.00. Alors, dans le traitement, j'aurai quelque-chose du genre
Code: Tout sélectionner
if (val != 4807)
{
  if (val > 1000)
  {
    ...
  }
  else
  {
    ...
  }
}

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 01 Nov 2012, 18:41

ouais, c'est tellement évident que t'as tord.

edit: apres relecture:
soit a != b
soit (a-b) != 0
La première expression est casse-cou. La seconde est la bonne méthode.

ah bon? pourquoi?
la vie est une fête :)

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

par Dlzlogic » 01 Nov 2012, 19:32

Autre exemple encore plus simple.
Je calcule le point M, milieu de AB.
Je compare les longueurs et les pentes des 2 1/2 segments.
Code: Tout sélectionner
Milieu Nombre de bons = 33  nombre de faux = 167

Concernant l'explication, c'est un peu plus compliqué, et comme je n'ai plus le document, je me limite à citer ce que j'ai lu.

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite