Making testfunc that allows 0.1 + 0.2 = 0.3

Viewed 90

I've just started my first programming course (in a while), and I'm working on the following task:

We are asked to make a function add(x,y) that adds the two arguments. We then implement this function in a testfunction, test_add(), and use an assert statement to make sure the add-function is working correctly. As long as the arguments are integers, all is fine. Then, we are asked to implement a test in our add-function to make sure that 0.1 + 0.2 = 0.3. I've read up on the topic, and know that their representation will be approximated using binary fraction, such that what I'm actually adding is 0.100000000000000005551115123126 + 0.2200000000000000011102230246252 = 0.30000000000000004 and therefore, my testfunction test_add() doesn't pass the pytest. One of the things I've tried is

def add(x,y, tol=1e-9):
    if abs(int(x) - x) <= tol:
        x == int(x)
    if abs(int(y) - y) <= tol:
        y == int(y)
 

    return x + y

I've also tried

def add(x,y, tol=1e-9):
   if isinstance(x, float):
        x == round(x, 1)
   if isinstance(y, float):
        y == round(y, 1)
   return x + y

Still no luck though... any hints on how I can implement this test to pass? Thanks in advance for all help and tips!! :)

3 Answers

You want to round the result of the addition, not the inputs to the method. i.e.

>>> round(.1, 1) + round(.2, 1) == .3
False
>>> round(.1 + .2, 1) == .3
True

So your add method could look like this:

def add(x, y):
   return round(x + y, 1)
>>> add(.1, .2) == .3
True

If you still want to keep the tolerance of the rounding, change the tol parameter to be the number of decimal places to keep:

def add(x, y, tol=9):
    return round(x + y, tol)
>>> add(.1, .2) == .3
True

On the other hand, usually when testing a float parameter, it's better to check the bounds and not the value exactly. You can do something like this.

>>> tol = 1e-9
>>> expected = .3
>>> actual = .1 + .2
>>> expected - tol <= actual <= expected + tol
True

Or more succinctly:

>>> abs(expected - actual) <= tol
True

If you're using Python3.5+ you have access to math.isclose() for these types of comparisons.

If you expect to calculate floating values in your function, it might be beneficial to use decimal.Decimal instead for this purpose.

from decimal import Decimal

def add_decimal(x, y):
    return Decimal(str(x)) + Decimal(str(y))

def add_float(x, y):
    return x + y

a = 0.1
b = 0.2
print("Decimal calculation:", add_decimal(a, b))
print("Float calculation:", add_float(a, b))

Output

Decimal calculation: 0.3
Float calculation: 0.30000000000000004
Related