224 votes

Comparer double à zéro à l’aide d’epsilon

Aujourd'hui, j'étais à la recherche par le biais de certains de code C++ (écrit par quelqu'un d'autre) et trouvé cet article:

double someValue = ...
if (someValue <  std::numeric_limits<double>::epsilon() && 
    someValue > -std::numeric_limits<double>::epsilon()) {
  someValue = 0.0;
}

Je suis à essayer de comprendre si ce même sens.

La documentation pour l' epsilon() dit:

La fonction renvoie la différence entre la 1 et la plus petite valeur supérieure à 1, qui est représentable [double].

Cela s'applique à 0, c'est à dire epsilon() est la plus petite valeur supérieure à 0? Ou il y a un nombre entre 0 et 0 + epsilon qui peut être représenté par un double?

Si pas, alors n'est-ce pas la comparaison équivalent à someValue == 0.0?

206voto

ybungalobill Points 31467

En supposant 64 bits IEEE double, il est de 52 bits de mantisse et 11 bits d'exposant. Regardez les numéros suivants:

1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^0 = 1

Représentable le plus faible nombre plus grand que 1:

1.0000 00000000 00000000 00000000 00000000 00000000 00000001 × 2^0 = 1 + 2^-52

Donc:

epsilon = (1 + 2^-52) - 1 = 2^-52

Existe-il des nombres entre 0 et epsilon? Beaucoup... E. g. le minimum positif représentable (normal) numéro est:

1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^-1022 = 2^-1022

En fait il y a environ (1022 - 52 + 1)×2^52 = 4372995238176751616 nombres entre 0 et epsilon, qui est d'environ 47% de tout le positif représentable, chiffres...

19voto

Steve Jessop Points 166970

Le test n'est certainement pas le même que someValue == 0. L'idée de nombres à virgule flottante, c'est qu'ils stocker un exposant et un significande. Elles représentent donc une valeur avec un certain nombre binaire de chiffres significatifs de précision (53 dans le cas de l'IEEE double). Le représentable, les valeurs sont beaucoup plus dense proche de 0 que ce qu'ils sont près de 1.

L'utilisation d'un système décimal familier, supposons que vous stocker une valeur décimale "à 4 chiffres significatifs" en exposant. Alors la prochaine représentable valeur supérieure à 1 est 1.001 * 10^0, et epsilon est 1.000 * 10^-3. Mais 1.000 * 10^-4 est également représentable, en supposant que l'exposant peut stocker -4. Vous pouvez prendre mon mot pour cela que, IEEE double peut stocker des exposants de moins que l'exposant de l' epsilon.

Vous ne pouvez pas dire à partir de ce code seul si cela a un sens de ne pas utiliser epsilon spécifiquement en tant qu'lié, vous avez besoin de regarder le contexte. Il se peut que l' epsilon est une estimation raisonnable de l'erreur dans le calcul qui a produit someValue, et il est peut-être qu'il ne l'est pas.

14voto

Skizz Points 30682

Il y a des nombres qui existent entre 0 et epsilon car epsilon est la différence entre le 1 et le plus grand nombre qui peut être représenté au-dessus de 1, et non la différence entre le 0 et le plus grand nombre qui peut être représenté au-dessus de 0 (si c'était le cas, ce code serait très peu):-

#include <limits>

int main ()
{
  struct Doubles
  {
      double one;
      double epsilon;
      double half_epsilon;
  } values;

  values.one = 1.0;
  values.epsilon = std::numeric_limits<double>::epsilon();
  values.half_epsilon = values.epsilon / 2.0;
}

À l'aide d'un débogueur, arrêter le programme à la fin du main et de regarder les résultats et vous verrez que epsilon / 2 est distincte de l'epsilon, zéro et un.

De sorte que cette fonction prend des valeurs entre +/- epsilon et les rend zéro.

5voto

pbhd Points 2530

Une aproximation d’epsilon (plus petite différence possible) autour d’un certain nombre (1.0, 0.0,...) peuvent être imprimées avec le programme suivant. Il affiche la sortie suivante :

Un peu fait penser clairement, que l’epsilon obtienne plus petit le plus petit nombre est nous utiliser pour observer ses epsilon-valeur, parce que l’exposant peut s’adapter à la taille de ce nombre.

3voto

Yakk Points 31636

Supposons que nous travaillons avec des jouets de nombres à virgule flottante qui s'inscrivent dans une 16 bits registre. Il y a un bit de signe, à 5 bits d'exposant, et à 10 bits de mantisse.

La valeur de ce nombre à virgule flottante est la mantisse, interprété comme un binaire de la valeur décimale deux fois à la puissance de l'exposant.

Autour de 1 l'exposant est égal à zéro. De sorte que le plus petit chiffre de la mantisse est une partie en 1024.

Près de 1/2 l'exposant est moins un, de sorte que la plus petite partie de la mantisse est à la moitié. Avec un cinq bits de l'exposant, il peut atteindre négatif de 16 ans, à quel point la plus petite partie de la mantisse est l'équivalent d'une partie de 32m. Et au moins 16 exposant, la valeur est autour d'une partie de 32k, beaucoup plus proche de zéro que l'epsilon autour de celui que nous avons calculé ci-dessus!

Maintenant, c'est un jouet à virgule flottante modèle qui ne correspond pas à tous les caprices d'un réel à virgule flottante du système , mais la capacité à refléter les valeurs plus petites que epsilon est raisonnablement similaire avec de vraies valeurs à virgule flottante.

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