problème d'arrondi en c++

problème d'arrondi en c++ - C++ - Programmation

Marsh Posté le 02-07-2004 à 15:06:30    

Bonjour,
Je développe avec DevCpp (toutes les options de compilation par défaut), et je rencontre le problème suivant: Quand j'incrémente une variable avec une valeur réelle (+0.1), puis la décrémente (-0.1), je ne reviens pas à 0, mais à une valeur très petite, du genre 6E-14.
 
Mon code est le suivant
 

Code :
  1. [#1cff00][#1cff00][#1cff00]#include <iostream>
  2. int main (int argc, char *argv[])
  3. {
  4.   float i = 0.0;
  5.   float j = (float)0.1; 
  6.   while(1){
  7.     cout << "\ni=" << i << "\tj=" << j;
  8.     if(i>=10) {
  9.         j = (float)(-0.1);
  10.         cin.get();
  11.     }
  12.     if(i<=0) {
  13.         j = (float)0.1;       
  14.         cin.get();
  15.     }
  16.     i += j;
  17.   } 
  18.   return 0;
  19. }


Le problème survient également en utilisant des "double"
Quelqu'un a-t-il déjà rencontré ce problème ?
 
Merci de votre aide

Reply

Marsh Posté le 02-07-2004 à 15:06:30   

Reply

Marsh Posté le 02-07-2004 à 16:06:48    

C'est un problème classique du a la gestion des nombres flottants dans les ordinateurs, le problème existe dans tous les calculs sur des flottants dans tous les langages

Reply

Marsh Posté le 02-07-2004 à 16:16:11    

float j = (float)0.1;  -> float j = 0.1f;

Reply

Marsh Posté le 03-07-2004 à 13:45:08    

Oui, c'est parce que à chaque fois que tu fais un calcul sur un flottant, le FPU fait une infime erreur. Ca se voit dans tous les langages, sur tous les CPUs, et c'est très chiant à gérer parfois...


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 13:47:33    

le fpu fait pas d'erreur, il calcule comme on a décidé qu'il devait calculer.

Reply

Marsh Posté le 03-07-2004 à 13:52:20    

j'ai dit ça par soucis de simplification, je t'avoue que je ne suis pas très au fait de ce genre de choses donc je suis bien incapable d'expliquer en détails d'où ça vient...


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 13:55:53    

« What every computer scientist should know about floating-point arithmetic »
 
en gros comment tu veux représenter l'ensemble des réesl |R avec n bits, n étant fini ?


Message édité par Taz le 03-07-2004 à 13:56:08
Reply

Marsh Posté le 03-07-2004 à 14:05:31    

Ca je l'avais compris :p. Qu'il fasse des approximations c'est évident, mais que ça implique des "erreurs" au moindre calcul ayant un résultat exact et fini c'est plus embêtant, même si c'est tout aussi inévitable à cause de la maniere dont sont stockées les valeurs. Pour aborder ça d'un point de vue electronique, et pour faire une analogie on rejoint la notion de Quantum des CAN/CNA : on ne peut coder qu'un nombre limitées de valeurs (2^n), qui ne comprennent pas les nombres flottants "finis"... (je suis pas sûr d'être clair [:mlc])


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 14:06:34    

(note bien la présence des guillemets autour d'erreur cette fois ci :d. J'entend erreur dans le résultat par rapport à ce qui était escompté, pas dans le fonctionnement même du fpu)


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 14:22:47    

« au moindre calcul ayant un résultat exact et fini c'est plus embêtant » parce qu'à part les calculs de limites, tu vois des calculs qui n'ont pas un résultat exact et fini ?

Reply

Marsh Posté le 03-07-2004 à 14:22:47   

Reply

Marsh Posté le 03-07-2004 à 14:26:40    

j'entendais par là quelques décimales, tu joues pas un peu sur les mots là ? :sarcastic:


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 14:29:48    

non, justement. la projection de |R sur [0; 2**n[ est imparfaite et irrégulière. si certains nombres ont une représentation exacte, c'est juste à cause de leur affinité avec la base 2 et le mode de représentation choisie.


Message édité par Taz le 03-07-2004 à 14:30:07
Reply

Marsh Posté le 03-07-2004 à 14:40:22    

je sais :jap:. C'est bien de ça que je parlais, mais je suis conscient de ne pas avoir été clair sur toutes la ligne.
Mon post précédent signifait résultat ayant un nombre de décimales apres la virgule fini (et non pas une valeur finie, pardon pour l'ambiguité).  
 
Comme la résolution d'un double ou d'un float (ou de n'importe quelle valeur codée sur quelque nombre de bits que ce soit) n'est pas infinie, impossible effectivement de retrouver cette exactitude sur un systeme informatique, sauf effectivement si ce nombre est inscriptible en base 2.
 
J'espere que c'est un peu plus clair. Je n'ai pas la prétention de t'apprendre quoi que ce soit hein :d. C'est juste pour clarifier ma réponse.
 
En somme tout ça poru dire que c'est normal qu'on trouve ce genre d'approximations dès qu'on fait des calculs sur des flottants.


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 14:43:06    

lis le pdf don't je t'ai parlé

Reply

Marsh Posté le 03-07-2004 à 14:46:28    

merci du conseil, ça peut etre enrichissant :jap:.


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 14:50:26    

http://www.google.com/search?num=5 [...] %7Clang_fr
c'est lequel ? (il y en a pas mal de différents [:spamafote])


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 14:53:16    

le goldberg

Reply

Marsh Posté le 03-07-2004 à 14:57:15    

c'est ce qu'il me semblait. :hello:


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 03-07-2004 à 18:51:20    

en fait qd on fait :
i = 0.1f, i ne vaut pas exactement 0.1, mais
(1+5033165*2^-23)/16, ce qui fait environ : 0,1000000015


Message édité par jcop le 03-07-2004 à 18:53:35
Reply

Marsh Posté le 07-07-2004 à 09:01:45    

Pour ton bout de programme, tu peux peut-être essayer autrement : au lieu de

Code :
  1. while 1){
  2.           cout << "\ni=" << i << "\tj=" << j;
  3.           if i>=10) {
  4.                 j = (float (-0.1);
  5.                 cin.get();
  6.           }
  7.           if i<=0) {
  8.                 j = (float 0.1;       
  9.                 cin.get();
  10.           }
  11.           i += j; 
  12.       }


 
essaie :

Code :
  1. float i = 0.0;
  2.       int j = 1;   // ou même float j; si tu préfère
  3.       while 1){
  4.           cout << "\ni=" << i << "\tj=" << j/10;
  5.           if i>=10) {
  6.                 j = -1;
  7.                 cin.get();
  8.           }
  9.           if i<=0) {
  10.                 j = 1;       
  11.                 cin.get();
  12.           }
  13.           i += j/10; 
  14.       }


 
je sais pas si ça marche mais logiquement...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed