53 votes

Double.Epsilon pour l'égalité, supérieur, inférieur, inférieur ou égal à, supérieur ou égal à

http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

Si vous créez un algorithme personnalisé qui détermine si deux virgule flottante les nombres peuvent être considérés comme égaux, vous devez utiliser une valeur qui est supérieure à l'Epsilon constant pour établir la acceptable absolue de la marge de différence pour les deux valeurs de considérées comme égales. (En général, que la marge de différence est de nombreuses fois plus de Epsilon.)

Donc, c'est pas vraiment un epsilon qui pourraient être utilisés pour des comparaisons? Je ne comprends pas vraiment la MSDN libellé.

Peut-il être utilisé comme epsilon dans les exemples ici? - http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison/253874#253874

Et enfin cela semble vraiment important donc je voudrais m'assurer d'avoir une mise en œuvre solide pour l'égalité, supérieur à, inférieur à, inférieur ou égal à, et supérieur ou égal à.

78voto

Hans Passant Points 475940

Je ne sais pas ce qu' ils ont de fumer quand ils ont écrit que. Double.Epsilon est représentable le plus faible de non-nombres dénormalisés valeur en virgule flottante qui n'est pas 0. Tout ce que vous savez est que, s'il y a une erreur de troncation, il sera toujours plus grande que cette valeur. Beaucoup plus grande.

Le Système.Double type peut représenter des valeurs exactes pour jusqu'à 15 chiffres. Ainsi, un simple d'abord afin d'estimer si une double valeur de x est égale à une constante est d'utiliser un epsilon de constante * 1E-15

    public static bool AboutEqual(double x, double y) {
        double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
        return Math.Abs(x - y) <= epsilon;
    }

Vous devez faire attention même si, les erreurs de troncature peut s'accumuler. Si x et y sont des valeurs calculées, alors vous devez augmenter l'epsilon.

46voto

Eric Lippert Points 300275

J'aimerais m'assurer d'avoir une mise en œuvre solide pour l'égalité, supérieur à, inférieur à, inférieur ou égal à, et supérieur ou égal à.

Vous utilisez binaire arithmétique à virgule flottante.

Binaire arithmétique à virgule flottante a été conçu pour représenter des grandeurs physiques comme la longueur, la masse, la charge, le temps, et ainsi de suite.

Sans doute, alors vous êtes à l'aide de binaire arithmétique à virgule flottante comme il était destiné à être utilisé: pour faire des opérations sur les grandeurs physiques.

Les mesures de grandeurs physiques ont toujours une certaine précision, en fonction de la précision de l'appareil utilisé pour la mesure.

Puisque c'est vous fournir les valeurs pour les quantités de la manipulation, vous êtes le seul qui sait ce que les "barres d'erreur" sont sur la quantité. Par exemple, si vous fournissez la quantité "de la hauteur du bâtiment est 123.56 mètres", alors vous savez que c'est précis au centimètre près, mais pas à l'ordre du micromètre.

Par conséquent, lors de la comparaison de deux quantités pour l'égalité, le sémantique est-à-dire "ce sont ces deux quantités égales dans les barres d'erreur spécifié par chaque mesure?"

Alors maintenant, nous avons la réponse à votre question. Ce que vous devez faire est de garder une trace de ce que l'erreur est sur chaque quantité; par exemple, la hauteur du bâtiment est "à l'intérieur de 0,01 à 123.56 mètres" parce que vous savez que c'est le degré de précision de la mesure. Si vous obtenez alors une autre mesure qui est 123.5587 et veulent savoir si les deux mesures sont "égaux" dans les tolérances, puis de faire de la soustraction et de voir si il tombe dans l'erreur de la tolérance. Dans ce cas, il n'. Si les mesures étaient en fait précise pour le micromètre, alors qu'ils ne sont pas égaux.

En bref: vous êtes la seule personne ici qui sait ce sensé tolérances sont, parce que vous êtes la seule personne qui sait où les chiffres de la manipulation est venu de la première place. Utiliser quelle que soit la tolérance de l'erreur de sens que pour vos mesures compte tenu de la précision de l'équipement dont vous avez utilisé pour le produire.

9voto

Jeffrey L Whitledge Points 27574

Si vous avez deux valeurs qui sont proches de la 1.0, mais ils diffèrent seulement dans leur least significant bits, alors la différence entre eux seront de plusieurs ordres de grandeur plus grand que le Double.Epsilon. En fait, la différence est de 324 décimal ordres de grandeur. C'est à cause de l'effet de l'exposant de la partie. Double.Epsilon a un énorme exposant négatif sur elle, tandis que 1.0 a un exposant de zéro (après les biais sont supprimés, bien sûr).

Si vous voulez comparer les deux valeurs sont similaires pour l'égalité, alors vous aurez besoin de choisir une coutume valeur epsilon qui est approprié pour les ordres de grandeur de la taille des valeurs à comparer.

Si le double des valeurs que vous êtes en comparant sont près de 1.0. Ensuite, la valeur de la moins siginificant bits serait près de 0.0000000000000001. Si le double des valeurs que vous êtes en comparant sont dans la trillions, alors la valeur du bit le moins significatif pourrait être un millier. Pas une seule valeur de epsilon pourrait être utilisée pour l'égalité des comparaisons à la fois de ces circonstances.

6voto

bassbytesbikes Points 477

Je viens de faire ceci - en utilisant l’idée de Kent Bogarts.

 private bool IsApproximatelyEqual(double x, double y, double acceptableVariance)
{
     double variance = x > y ? x - y : y - x;
     return variance < acceptableVariance;

     //or
     //return Math.Abs(x - y) < acceptableVariance;
}
 

4voto

Kent Boogaart Points 97432

Il peut être utilisé pour des comparaisons, en supposant que vous souhaitiez vous assurer que les deux valeurs sont exactement égales ou ont la plus petite différence représentable pour le type double. De manière générale, vous voudriez utiliser un nombre supérieur à double.Epsilon pour vérifier si deux doubles sont approximativement égaux.

Pourquoi le framework .NET ne définit pas quelque chose comme

 bool IsApproximatelyEqual(double value, double permittedVariance);
 

est au delà de moi.

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