# Unittest (sometimes) fails because floating-point imprecision

## Question:

I have a class Vector that represents a point in 3-dimensional space. This vector has a method `normalize(self, length = 1)` which scales the vector down/up to be `length == vec.normalize(length).length`.

The unittest for this method sometimes fails because of the imprecision of floating-point numbers. My question is, how can I make sure this test does not fail when the methods are implemented correctly? Is it possible to do it without testing for an approximate value?

``````    def testNormalize(self):
vec = Vector(random.random(), random.random(), random.random())
self.assertEqual(vec.normalize(5).length, 5)
``````

This sometimes results in either `AssertionError: 4.999999999999999 != 5` or `AssertionError: 5.000000000000001 != 5`.

Note: I am aware that the floating-point issue may be in the `Vector.length` property or in `Vector.normalize()`.

I suppose one possibility is to apply the function to test cases for which all inputs, the results of all intermediate calculations, and the output are exactly representable by `float`.

To illustrate:

``````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
``````

Not sure how practical this is though…

### 1) How can I make sure the test works?

Use `assertAlmostEqual`, `assertNotAlmostEqual`.

From the official documentation:

``````assertAlmostEqual(first, second, places=7, msg=None, delta=None)
``````

Test that first and second are approximately equal by computing the difference, rounding to the given number of decimal places (default 7), and comparing to zero.

### 2) Is it possible to do it without testing for an approximate value?

Esentially No.

The floating point issue can’t be bypassed, so you have either to "round" the result given by `vec.normalize` or accept an almost-equal result (each one of the two is an approximation).

By using a floating point value, you accept a small possible imprecision. Therefore, your tests should test if your computed value falls in an acceptable range such as:

``````theoreticalValue - epsilon < normalizedValue < theoreticalValue + epsilon
``````

where `epsilon` is a very small value that you define as acceptable for a variation due to floating point imprecision.

In general, you should not assert equality for floats. Instead, ensure that the result is within certain bounds, e.g.:

``````self.assertTrue(abs(vec.normalize(5).length - 5) < 0.001)
``````
Categories: questions
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.