Perte de precision dans la division

Salut, j'ai un probleme avec une comparaison qui ne marche pas.
besoin de votre aide
#include <iostream>
using namespace std;
int main()
{
    float y;
    y=1/(1/float(2)-1/float(3));
    cout<<y<<"\t"<<"normalement y==int(y) ... mais ..."<<endl;
    if (y==int(y))
        cout<<"cool"<<endl;
    else
        cout<<"ne marche pas"<<endl;
    y=1/float(2)+1/float(2);
    cout<<y<<endl;
    if (y==int(y))
        cout<<"now it works!!!!!"<<endl;
    return 0;
}

4 réponses

  1. Contributeur
    bonjour. quel est ton problème: as-tu une erreur de compilation? laquelle?
    si ton programme ne donne pas le résultat que tu attends, peux-tu nous expliquer le résultat obtenu et le résultat attendu?
    que pourrais-tu faire de plus pour comprendre ce que fait ton programme?
    as-tu essayé de faire ces calculs avec une calculatrice, pour comparer?
    0
    1. Bonjour,
      Il ne faut pas confondre mathématiques et informatique.
      En math 1/2 - 1/3 vaut 1/6.
      En informatique, les nombres ne sont généralement pas des nombres réels mais des approximations, on aura 1.0/2.0 - 1.0/3.0 vaut environ 1.0/6.0.
      Exemple :
      if ( 1.f + 0.0000000001f == 1.f )       // vrai!
      cout << 1e-45f * 100;                   // affiche 1.401e-43!
      D'où la règle : ne jamais faire un test d'égalité sur un float ou un double
      0
      1. yg-ben j crois que tout est expliqué dans le code source,
        dalfan j comprends maintenant, merci. Mais y a t il ps des méthodes pour comparer, j'en ai bien besoin dans un programme
        0
        1. Avec des float et double à cause de l'imprécision tout test d'égalité est un problème.
          • On le résout le plus souvent en évitant les flottants et en posant le test différemment; par exemple, est-ce que : ( x / (float)y ) est un entier? devient est-ce que : x % y est nul?
          • On peut aussi utiliser une bibliothèque (ou créer ses propres objets) qui évite les flottants. Par exemple avec un type 'Fraction' qui évite des divisions.
          • Sinon on peut toujours effectuer des tests d'inégalité, par exemple, if (x > 5.9 && x < 6.1) // pour un x proche de 6.
          • On peut créer une fonction qui effectue ce genre de test (ici template pour gérer float et double)
            template<class T> inline bool quasi_egaux(T const& x , T const& y) {
              return std::abs(x-y) < std::numeric_limits<T>::epsilon() * std::abs(x+y)
                    || std::abs(x-y) < std::numeric_limits<T>::min();
            }
            Elle accepte une erreur de 2 bits de précision. Mais c'est rarement un bon moyen.
          0