220 votes

Sens de l’argument d’epsilon d’assertEquals pour les valeurs double

J’ai une question pour junit assertEquals pour tester les valeurs double. Doc API de lecture que je vois :

Déconseillée. Utilisez assertEquals (double prévu, double, double, véritable epsilon) à la place

Que signifie valeur epsilon ? (Epsilon est une lettre dans l’alphabet grec, droite ?).

Quelqu'un peut m’expliquer comment l’utiliser ?

238voto

jberg Points 2246

Epsilon est la valeur que les 2 nombres peuvent être décalé de. Donc il affirmera true tant que``

135voto

Hound Dog Points 3240

La version de Junit est-ce? Je n'ai jamais vu de delta, pas epsilon - mais c'est une question de côté!

De JUnit javadoc:

delta - le maximum de delta entre le rendement prévu et réel pour lequel les deux les numéros sont toujours considérés comme des égaux.

C'est probablement excessif, mais je l'utilise généralement un très petit nombre, par ex.

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertEquals(123.456, 123.456, DELTA);
}

59voto

mdma Points 33973

Les calculs en virgule flottante ne sont pas exactes, il y a souvent des erreurs d'arrondi, et les erreurs dues à la représentation. (Par exemple, de 0,1 ne peut pas être exactement représenté en virgule flottante binaire.)

De ce fait, directement de la comparaison de deux valeurs à virgule flottante pour l'égalité est généralement pas une bonne idée, car ils peuvent être différents en une petite quantité, selon la façon dont ils ont été calculés.

Le "delta", comme on les appelle dans le JUnit javadoc, décrit le montant de la différence que vous pouvez tolérer dans les valeurs pour eux d'être toujours considérés comme égaux. La taille de cette valeur est entièrement tributaire des valeurs que vous comparez. Lorsque l'on compare les doubles, je l'utilise généralement la valeur attendue divisé par 10^6.

13voto

Edwin Dalorzo Points 19899

Le truc, c'est que les deux peuvent ne pas être exactement égal en raison de la précision des questions inhérentes à des nombres à virgule flottante. Avec cette valeur delta vous pouvez contrôler l'évaluation de l'égalité fondée sur un facteur d'erreur.

Aussi certaines valeurs à virgule flottante peuvent avoir des valeurs spéciales, comme NAN et -l'Infini à+l'Infini, qui peut influencer les résultats.

Si vous avez vraiment l'intention de comparer que les deux doubles sont exactement égales par ailleurs, il est préférable de les comparer comme un long représentation

Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));

Ou

Assert.assertEquals(0, Double.compareTo(expected, result));

Qui peut prendre ces nuances en compte.

Je n'ai pas fouillé dans la méthode Assert en question, mais je ne peux que supposer que la précédente a été supprimée pour ce genre de questions et que le nouveau ne prendre en compte.

2voto

David Moles Points 7669

Notez que si vous n'êtes pas à faire des mathématiques, il n'y a rien de mal à faire valoir exacte des valeurs à virgule flottante. Par exemple:

public interface Foo {
    double getDefaultValue();
}

public class FooImpl implements Foo {
    public double getDefaultValue() { return Double.MIN_VALUE; }
}

Dans ce cas, vous voulez vous assurer qu'il est vraiment MIN_VALUE, pas à zéro ou -MIN_VALUE ou MIN_NORMAL ou une autre valeur très faible. Vous pouvez dire

double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);

mais ainsi, vous obtenez une dépréciation d'avertissement. Pour éviter cela, vous pouvez appeler assertEquals(Object, Object) à la place:

// really you just need one cast because of autoboxing, but let's be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);

Et, si vous voulez vraiment astucieux:

assertEquals(
    Double.doubleToLongBits(Double.MIN_VALUE), 
    Double.doubleToLongBits(defaultValue)
);

Ou vous pouvez simplement utiliser Hamcrest couramment style assertions:

// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));

Si la valeur que vous êtes à la vérification de la ne viennent de faire quelques calculs, cependant, l'utilisation de l'epsilon.

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