31 votes

La conversion d'une chaîne en double équivaudra-t-elle au double littéral?

Par exemple:

 assert(atof("1.2") == 1.2);
 

quel que soit le flotteur utilisé?

Je comprends que la précision en virgule flottante n'est pas exacte, mais elle est précisément inexacte, donc l'arrondi en binaire produit-il exactement le même double?

29voto

Eric Postpischil Points 36641

Ce n'est pas garanti par la norme. La sémantique de conversion en virgule flottante littérale dans le code source sont spécifiées dans C 2011 [projet de N1570] 6.4.4.2. Cela indique que le recommandé, mais pas obligatoire, la pratique est que la traduction en temps de conversion de les constantes en virgule flottante doit correspondre au temps d'exécution de la conversion de chaînes de caractères par des fonctions de la bibliothèque, comme strtod.

De plus, la norme n'exige même pas que les deux littéraux avec la même valeur mathématique, comme 1.23 et 1.230, de se convertir à la même valeur. Ces exemples proviennent de note de bas de page 75 dans la norme, qui est une référence à un paragraphe indiquant que toutes les constantes en virgule flottante de la même source, la forme doit se convertir à la même valeur. Ainsi, 1.23 convertit toujours à la même valeur partout où il apparaît dans la source, mais 1.230 n'a pas nécessairement de se convertir à la même valeur qu' 1.23 ou 123e-2. Même 123e-2 et 123e-02 peuvent être différentes.

atof(p) est spécifié dans 7.22.1.2 être l'équivalent d' strtod(p, (char **) NULL) sauf pour la façon dont ils se comportent avec des erreurs. strtod est spécifié dans 7.22.1.3. Cette clause a certaines pratiques recommandées pour la précision, mais il est muet sur la correspondance de la traduction en temps de conversion de littéraux.

1voto

Bob Jarvis Points 14906

Cette vérification dépendra inévitablement de l'implémentation, j'ai donc écrit le petit script de test suivant:

 #include <stdio.h>
#include <stdlib.h>

int main()
  {
  double d1 = 1.2;
  double d2 = atof("1.2");
  char *p;
  double d3 = strtod("1.2", &p);

  printf("d1 = %40.40f\n", d1);
  printf("d2 = %40.40f\n", d2);
  printf("d3 = %40.40f\n", d3);

  if(d1 != d2)
    printf("d1 != d2\n");

  if(d2 != d3)
    printf("d2 != d3\n");
  }
 

Dans le cas du compilateur HP C / C ++, version A.06.25.02, cette sortie

 d1 = 1.1999999999999999555910790149937383800000
d2 = 1.1999999999999999555910790149937383800000
d3 = 1.1999999999999999555910790149937383800000
 

ce qui démontre que la conversion (de 1.2, au moins) qui est effectuée par le compilateur correspond aux conversions effectuées par atof et strtod .

-5voto

ChristineDD Points 3

Du génie militaire, nous tenons toujours compte de ce problème en plaçant une bande de tolérance, disons +/- 0,000001 autour de la valeur de comparaison réelle du flotteur. De cette façon, vous savez ce que vous comparez vraiment et vous évitez de polluer ce que l'algorithme est conçu pour faire. On travaille toujours avec des nombres flous lorsque l'on travaille avec des nombres à virgule flottante sur lesquels on ne peut ou ne doit pas faire une comparaison difficile.

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