[Python-ideas] PEP 485: A Function for testing approximate equality

M.-A. Lemburg mal at egenix.com
Fri Feb 6 17:07:33 CET 2015


There seems to be a typo in the PEP:

"""
The new function will have the following signature:

is_close(a, b, rel_tolerance=1e-9, abs_tolerance=0.0)

a and b : are the two values to be tested to relative closeness

rel_tolerance : is the relative tolerance -- it is the amount of error allowed, relative to the
magnitude a and b. For example, to set a tolerance of 5%, pass tol=0.05. The default tolerance is
1e-8, which assures that the two values are the same within about 8 decimal digits.

abs_tolerance : is an minimum absolute tolerance level -- useful for comparisons near zero.
"""

Note that the description says 1e-8 whereas the signature says
1e-9.

The github link in the PEP gives a 404:

https://github.com/PythonCHB/close_pep/blob/master


In general, I think the PEP approaches the problem from a slightly
different angle than one might expect.

I don't really want to continue the bike shedding around the PEP, but
just add a slightly different perspective which might be useful as
additional comment in the PEP.

In practice, you'd probably want to check whether the result of a computation
(the approximation) is within an certain *precision range* around the
true value, in other words, you're interested in either the
absolute error of your calculation when assuming that the true value
is 0.0 and the relative one otherwise.

Say your true value is v and the calculated one v_approx.
The absolute error is abs(v - v_approx), the relative error
abs(1 - v_approx/v) (for v != 0).

This gives the following implementation:

"""
_debug = False

def reasonably_close(v_approx, v, max_rel_error=1e-8, max_abs_error=1e-8):

    """ Check whether the calculated value v_approx is within
        error range of the true value v.

        If v == 0.0, an absolute error check is done using max_abs_error as
        valid error range.

        For all other values, a relative error check is done using
        max_rel_error as basis.

        This is done, since it is assumed that if you're calculating a value
        close to a value, you'd expect the calculation to be correct within
        a certain precision range.

    """
    if v == 0.0:
        # Use the absolute error as basis when checking calculations which
        # should return 0.0.
        abs_error = abs(v_approx - v)
        if _debug:
            print ('abs error = %s' % abs_error)
        return (abs_error <= max_abs_error)

    # Use the relative error for all other true values.
    rel_error = abs(1 - v_approx / v)
    if _debug:
        print ('rel error = %s' % rel_error)
    return (rel_error <= max_rel_error)

# Test equal values
assert reasonably_close(0.0, 0.0)
assert reasonably_close(1e-8, 1e-8)
assert reasonably_close(1.0, 1.0)

# Test around 0.0
assert reasonably_close(1e-8, 0.0)
assert not reasonably_close(2e-8, 0.0)
assert reasonably_close(1e-8, 1e-8)
assert not reasonably_close(2e-8, 0.0)

# Test close to 0.0
assert reasonably_close(1e-8 + 1e-20, 1e-8)
assert reasonably_close(1e-8 + 1e-16, 1e-8)
assert not reasonably_close(1e-8 + 2e-16, 1e-8)

# Test around 1.0
assert reasonably_close(1 + 1e-8, 1.0)
assert not reasonably_close(1 + 2e-8, 1.0)

# Test large values
assert reasonably_close(1e8 + 1, 1e8)
assert not reasonably_close(1e8 + 2, 1e8)
assert reasonably_close(1e9 + 1, 1e9)
assert reasonably_close(1e9 + 2, 1e9)
assert reasonably_close(1e9 + 10, 1e9)
assert not reasonably_close(1e9 + 11, 1e9)
assert reasonably_close(1e-9, 0.0)
assert reasonably_close(1 + 1e-9, 1.0)

# Test negative values
assert reasonably_close(-1.0, -1.0)
assert reasonably_close(-1e-8, 0.0)
assert reasonably_close(-1 - 1e-8, -1.0)
assert reasonably_close(-1e-9, 0.0)
assert reasonably_close(-1 - 1e-9, -1.0)

# Test different signs
assert not reasonably_close(0.0, 1.0)
assert not reasonably_close(0.0, -1.0)
assert not reasonably_close(1.0, -1.0)
"""

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source  (#1, Feb 06 2015)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> mxODBC Plone/Zope Database Adapter ...       http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ...        http://python.egenix.com/
________________________________________________________________________

::::: Try our mxODBC.Connect Python Database Interface for free ! ::::::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611
               http://www.egenix.com/company/contact/


More information about the Python-ideas mailing list