c ++ comparaison de deux valeurs doubles ne fonctionnant pas correctement

Regardez ce code:

#include  #include  using namespace std; class Sphere { double r; public: double V() const { return (4/3) * 3.14 * pow(r,3); } bool equal(const Sphere& s) const { cout << V() << " == " << sV() << " : " << ( V() == sV() ); return ( V() == sV() ); } explicit Sphere(double rr = 1): r(rr){} }; main() { Sphere s(3); s.equal(s); } 

La sortie est 84.78 == 84.78 : 0 ce qui signifie que la même méthode ne renvoie pas la même valeur à chaque fois, même si tous les parameters sont statiques?

Mais si j’écris 3.0 au lieu de 3.14 dans la définition de la méthode V() , comme ceci:

 double V() const { return (4/3) * 3.0 * pow(r,3); } 

La sortie est alors: 84.78 == 84.78 : 1

Qu’est-ce qui se passe ici? J’ai besoin de cette méthode, pour mon programme, qui permettra de comparer les volumes de deux objects, mais est-ce impossible? Je me suis cogné la tête pendant si longtemps pour comprendre quelle est la cause du problème et, heureusement, je l’ai trouvé, mais je ne comprends pas pourquoi. Cela at-il quelque chose à voir avec le compilateur (GCC) ou manque-t-il quelque chose d’important ici?

La comparaison de valeurs en virgule flottante à l’aide de l’opérateur == est très sujette aux erreurs; deux valeurs qui devraient être égales peuvent ne pas être dues à des erreurs d’arrondi arithmétiques. La manière courante de les comparer consiste à utiliser un epsilon:

 bool double_equals(double a, double b, double epsilon = 0.001) { return std::abs(a - b) < epsilon; } 

Les comparaisons en virgule flottante posent deux problèmes:

(1) Les opérations en virgule flottante impliquent généralement au moins de petites erreurs d’arrondis difficiles à prévoir. Par conséquent, deux opérations en virgule flottante devant donner mathématiquement le même résultat (comme 4.7 * (1.0 / 3.14) vs 4.7 / 3.14) peuvent donner des résultats différents.

(2) Le compilateur est autorisé à effectuer des opérations en virgule flottante avec parfois une précision supérieure à celle nécessaire. Il est également permis d’effectuer exactement les mêmes opérations en virgule flottante avec la précision nécessaire à d’autres moments. Par conséquent, la même opération peut produire des résultats légèrement différents, ce que vous voyez ici.

Pour résoudre le problème du PO, cela semble être causé par (2). J’essaierais de trouver s’il existe des options de compilateur pouvant empêcher le compilateur d’utiliser une précision supérieure à celle requirejse.