2011-05-07 2 views
3

Possible en double:
Manipulating and comparing floating points in javala comparaison des nombres à virgule flottante en Java

Suis-je censé utiliser un Epsilon en comparant les nombres à virgule flottante en Java? Est-ce que la méthode statique Float.compare (float f1, float f2) est sûre à utiliser?

Merci!

EDIT: Je pense que je l'ai eu. Quand j'écris, disons, 3.6f en éclipse, le compilateur interprète ce nombre comme 3.6. Cependant, quand j'écris 1.2f * 3.0f, le résultat est 3.6000001. Alors que mathématiquement c'est faux, ces deux résultats sont évidemment inégaux. D'où la nécessité d'avoir un epsilon tout en vérifiant l'égalité. Cependant, lorsque j'écris 0.0f dans eclipse, le compilateur interprète cela strictement comme 0 parce que IEEE 754 est capable de le gérer correctement. Par conséquent, s'assurer qu'un flotteur est strictement positif avec (valeur> 0.0f) est correct.

Le seul problème que je vois est lorsque l'ordinateur n'utilise pas la représentation IEEE 754, et utilise à la place une représentation qui ne gère pas 0 correctement.

Ai-je raison?

+1

La réponse dépend de ce que vous essayez de faire. En fait, si vous devriez utiliser le point flottant ou non dépend également de cela. Expliquez le problème à la main, seulement alors vous obtiendrez une réponse utile. –

+0

Coffre-fort de quelle manière? C'est une méthode pratique et peut gérer certains cas de bords, mais cela ne nous empêchera pas de créer nos propres bogues. Aussi, j'ai utilisé un epsilon en essayant d'implémenter ma propre méthode d'égalité pour les nombres à virgule flottante, mais pas en les comparant. –

+0

Désolé de ne pas être suffisamment précis. J'écris des particules pour un jeu. Je veux savoir quand deltaTime (float) est égal à 0.0, car je calcule la vitesse en utilisant velocity = distance * (1/deltaTime). Avoir une vitesse infinie est un peu stupide. Pour le moment j'utilise (Float.compare (deltaTime, 0.0f)! = 0) pour m'assurer que deltaTime est supérieur à 0.0. Le deltaTime NE PEUT PAS être inférieur à 0. – Klems

Répondre

3

Oui, il est conseillé d'utiliser une tolérance pour vérifier la valeur absolue de la différence entre deux nombres flottants. Compare vous indique si un double est inférieur, égal ou supérieur à un autre. Il ne vous dira pas à quel point ils sont proches les uns des autres, donc, pas, ce n'est pas plus sûr que de comparer avec ==.

+0

+ 1, annuler mon édition si vous ne l'aimez pas ;-) – aioobe

+0

Non, c'est bien. – duffymo

12

La méthode Math.ulp() a une utilisation pratique lors des tests. Comme vous le savez sans doute, vous ne devriez généralement pas comparer les nombres à virgule flottante pour l'égalité exacte. Au lieu de cela, vous vérifiez qu'ils sont égaux dans une certaine tolérance. Par exemple, dans JUnit vous comparez les valeurs attendus à virgule flottante réels comme ceci:

assertEquals(expectedValue, actualValue, 0.02);

Cela affirme que la valeur réelle est à 0,02 de la valeur attendue. Cependant 0,02 est-il une tolérance raisonnable? Si la valeur attendue est 10.5 ou -107.82, alors 0.02 est probablement correct. Cependant, si la valeur attendue est de plusieurs milliards, alors le 0,02 peut être complètement indiscernable de zéro. Souvent, ce que vous devriez tester est l'erreur relative en termes de ULP. En fonction de la précision requise par le calcul, vous sélectionnez généralement une tolérance comprise entre 1 et 10 ULP. Par exemple, ici, je précise que le résultat réel doit être dans les 5 ULPs de la valeur réelle:

assertEquals(expectedValue, actualValue, 5*Math.ulp(expectedValue));

http://www.ibm.com/developerworks/java/library/j-math2/index.html

+0

Et si une valeur est grande et l'autre petite? Est-ce que prendre l'ULP de la somme est une bonne idée? – Winter

Questions connexes