63 votes

Comparaison en virgule flottante

 int main()
{
    float a = 0.7;
    float b = 0.5;
    if (a < 0.7)
    {
       if (b < 0.5) printf("2 are right");
       else         printf("1 is right");
    }
    else printf("0 are right");
}
 

J'aurais prévu que la sortie de ce code soit 0 are right . Mais à mon grand désarroi, la sortie est 1 is right pourquoi?

130voto

Cicada Points 19550
int main()
{
    float a = 0.7, b = 0.5; // These are FLOATS
    if(a < .7)              // This is a DOUBLE
    {
      if(b < .5)            // This is a DOUBLE
        printf("2 are right");
      else
        printf("1 is right");
    }
    else
      printf("0 are right");
}

Les flotteurs d'obtenir une promotion au double au cours de la comparaison, et depuis les flotteurs sont moins précis que doublé, de 0,7 comme le flotteur est pas la même chose que de 0,7 double. Dans ce cas, de 0,7 en tant que float devient inférieure à 0,7 double quand il sera promu. Et comme Christian a dit, 0,5 étant une puissance de 2 est toujours représenté exactement, de sorte que le test fonctionne comme prévu: 0.5 < 0.5 est faux.

Donc, soit:

  • Variation float de double, ou:
  • Variation .7 et .5 de .7f et .5f,

et vous permettra d'obtenir le comportement attendu.

3voto

Win32.Neshto Points 202

Cela est dû à des problèmes d'arrondi lors de la conversion de float à double

2voto

Richard Tingle Points 8054

Généralement, la comparaison de l'égalité avec les flotteurs est une entreprise dangereuse (ce qui est effectivement ce que vous faites pendant que vous êtes en comparant droit sur la limite de l' > ), n'oubliez pas que dans certaines fractions décimales (comme 1/3) ne peut pas être exprimé exactement, la même chose peut être dit de binaire,

0.5= 0.1, sera la même en float ou double.

0.7=0.10110011001100 etc toujours, de 0,7 ne peut pas être exactement représenté en binaire, vous obtenez des erreurs d'arrondi et peut être (très très légèrement) différente entre float et double

Notez que le fait d'aller entre les chars et les doubles vous coupez un différent nombre de décimales, donc votre incompatible résultats.

0voto

Jay Kramer Points 174

Aussi, btw, vous avez une erreur dans votre logique de 0 sont de droite. Vous ne cochez pas b lors de la sortie 0 est la droite. Mais le tout est un peu mystérieux dans ce que vous êtes vraiment essayer de l'accomplir. Virgule flottante comparaisons entre les flotteurs et du double ont des variations, des minutes, de sorte que vous devriez comparer avec un delta "acceptable" variation pour votre situation. J'ai toujours fait via les fonctions inline qui vient d'effectuer le travail (il l'a fait une fois avec une macro, mais c'est trop salissant). De toute façon, yah, l'arrondissement questions sont nombreuses avec ce type d'exemple. Lire la virgule flottante choses, et de savoir que .7 est différent .7f et l'attribution .7 à un flotteur sera de voter pour un double en un float, et donc de changer la nature exacte de la valeur. Mais, la programmation hypothèse sur b est faux puisque vous avez coché une retentissait à moi, et j'ai dû constater qu' :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X