J'ai une classe Vector qui représente un point dans un espace tridimensionnel. Ce vecteur a une méthode normalize(self, length = 1)
qui réduit le vecteur à length == vec.normalize(length).length
.
Le testeur pour cette méthode parfois échoue à cause de l'imprécision des nombres à virgule flottante. Ma question est la suivante: comment puis-je m'assurer que ce test n'échoue pas lorsque les méthodes sont correctement implémentées? Est-il possible de le fairesanstester une valeur approximative?
Information additionnelle :
def testNormalize(self):
vec = Vector(random.random(), random.random(), random.random())
self.assertEqual(vec.normalize(5).length, 5)
Ceciparfoisrésulte en AssertionError: 4.999999999999999 != 5
ou AssertionError: 5.000000000000001 != 5
.
Note: Je suis conscient que le problème de virgule flottante peut être dans la propriété Vector.length
ou dans Vector.normalize()
.
Utilisez assertAlmostEqual
, assertNotAlmostEqual
.
De la documentation officielle :
assertAlmostEqual(first, second, places=7, msg=None, delta=None)
Vérifiez que les première et seconde sont approximativement égales en calculant la différence, en arrondissant au nombre de décimales donné (7 par défaut) et en effectuant une comparaison à zéro.
Essentiellement Non.
Le problème de virgule flottante ne peut pas être ignoré, vous devez donc "arrondir" le résultat donné par vec.normalize
ou accepter un résultat presque égal (chacun des deux est une approximation).
En utilisant une valeur à virgule flottante, vous acceptez une petite imprécision possible. Par conséquent, vos tests doivent vérifier si votre valeur calculée se situe dans une plage acceptable, telle que:
theoreticalValue - epsilon < normalizedValue < theoreticalValue + epsilon
où epsilon
est une très petite valeur que vous définissez comme acceptable pour une variation due à une imprécision en virgule flottante.
En général, vous ne devriez pas affirmer l'égalité pour les flottants. Au lieu de cela, assurez-vous que le résultat se situe dans certaines limites, par exemple:
self.assertTrue(abs(vec.normalize(5).length - 5) < 0.001)
Je suppose qu’une possibilité consiste à appliquer la fonction à des cas de test pour lesquels toutes les entrées, les résultats de tous les calculs intermédiaires et la sortie sont exactement représentables par float
.
Pour illustrer:
In [2]: import math
In [4]: def norm(x, y):
...: return math.sqrt(x*x + y*y)
...:
In [6]: norm(3, 4) == 5
Out[6]: True
Je ne sais pas si c'est pratique, cependant ...