D'après ce que je comprends des règles des comparaisons en virgule flottante IEEE-754, tous les opérateurs de comparaison, à l'exception de !=
retournera false si l'un ou l'autre ou les deux arguments sont des NaN, tandis que la fonction !=
retournera vrai. Je peux facilement reproduire ce comportement avec un simple test standalone :
for (int ii = 0; ii < 4; ++ii)
{
float a = (ii & 1) != 0 ? NAN : 1.0f;
float b = (ii & 2) != 0 ? NAN : 2.0f;
#define TEST(OP) printf("%4.1f %2s %4.1f => %s\n", a, #OP, b, a OP b ? "true" : "false");
TEST(<)
TEST(>)
TEST(<=)
TEST(>=)
TEST(==)
TEST(!=)
}
Ceci imprime les résultats attendus : (NaN est formaté en tant que -1.$
dans le runtime MSVC)
1.0 < 2.0 => true
1.0 > 2.0 => false
1.0 <= 2.0 => true
1.0 >= 2.0 => false
1.0 == 2.0 => false
1.0 != 2.0 => true
-1.$ < 2.0 => false
-1.$ > 2.0 => false
-1.$ <= 2.0 => false
-1.$ >= 2.0 => false
-1.$ == 2.0 => false
-1.$ != 2.0 => true
1.0 < -1.$ => false
1.0 > -1.$ => false
1.0 <= -1.$ => false
1.0 >= -1.$ => false
1.0 == -1.$ => false
1.0 != -1.$ => true
-1.$ < -1.$ => false
-1.$ > -1.$ => false
-1.$ <= -1.$ => false
-1.$ >= -1.$ => false
-1.$ == -1.$ => false
-1.$ != -1.$ => true
Cependant, lorsque je colle ce morceau de code dans les profondeurs des boucles internes de mon application, où tous les calculs en virgule flottante sont effectués, j'obtiens ces résultats inexplicables :
1.0 < 2.0 => true
1.0 > 2.0 => false
1.0 <= 2.0 => true
1.0 >= 2.0 => false
1.0 == 2.0 => false
1.0 != 2.0 => true
-1.$ < 2.0 => true
-1.$ > 2.0 => false
-1.$ <= 2.0 => true
-1.$ >= 2.0 => false
-1.$ == 2.0 => true
-1.$ != 2.0 => false
1.0 < -1.$ => true
1.0 > -1.$ => false
1.0 <= -1.$ => true
1.0 >= -1.$ => false
1.0 == -1.$ => true
1.0 != -1.$ => false
-1.$ < -1.$ => true
-1.$ > -1.$ => false
-1.$ <= -1.$ => true
-1.$ >= -1.$ => false
-1.$ == -1.$ => true
-1.$ != -1.$ => false
Pour une raison quelconque, le <
, <=
y ==
renvoient inopinément un résultat vrai lorsque l'un ou les deux arguments sont des NaN. De plus, les !=
renvoie inopinément un faux.
Il s'agit de code 64 bits, construit avec Visual Studio 2010, fonctionnant sur un Intel Xeon E5-2650. Utilisation de _mm_getcsr()
J'ai confirmé que le registre CSR a la même valeur dans les deux scénarios.
Qu'est-ce qui pourrait encore influencer le comportement des mathématiques à virgule flottante de cette manière ?