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

Guido van Rossum guido at python.org
Tue Jan 27 19:37:38 CET 2015


On Tue, Jan 27, 2015 at 9:07 AM, Chris Barker <chris.barker at noaa.gov> wrote:

> On Tue, Jan 27, 2015 at 8:20 AM, Guido van Rossum <guido at python.org>
> wrote:
>
>> A) Which test do we use:
>>>   1) The asymmetric test
>>>   2) The "strong" test (minimum relative tolerance)
>>>   3) The "weak" test (maximum relative tolerance)
>>>
>>
>> The problem with this question is that, while it's easy to come up with
>> examples where it may matter (e.g. 95 is within 5% of 100, but 100 is not
>> within %5 of 95), in practice the tolerance is more likely to be 1e-8, in
>> which case it doesn't matter.
>>
>
> Exactly why I'm happy with any of them. I'm trying to suss out whether
> anyone else has a reason to reject one or the others. If no one does, then
> we can just pick one.
>

By now can't you summarize the reasons that others have brought up?

>
>
>
>> B) Do we provide a non-zero default for the absolute tolerance? If so
>>> what should the value be? Remember that this serves primarily to provide a
>>> check against zero.
>>>
>>
>> It feels like absolute tolerance is a completely different test. And it
>> is a much simpler test for which w don't need a helper function -- it's
>> just abs(x) < tolerance.
>>
>> When does a program need *both* absolute and relative tolerance in a
>> single test?
>>
>
> Because we want it to be able to do something sane when comparing to zero
> -- the abs_tolerance allows you to set a minimum tolerance that will do
> something reasonable near zero (we could use a zero_tolerance, as Nathaniel
> has suggested, instead, but that creates the incontinuity that , for
> example, 1e-12 is close to zero, but it is not close to 1e-100 -- I think
> that's a bad idea for a call with the same arguments). I spend a good while
> thinking about this and playing with it, and it became clear to me that
> this is the best way to go for a not-to-surprising result. And it's
> consistent with what numpy and Steven's statistics test code does.
>

I don't think you can have this always be sane. For someone who for
whatever reason is manipulating quantities that are in the range of 1e-100,
1e-12 is about as large as infinity.

I think my reasoning comes down to the same rule I often use to decide
whether we need one function or two -- if in every use case you always know
whether you need version A or version B, then it's better to have two
functions rather than a single one with a flag to request A or B.

And isn't it the case that whenever you are comparing to zero, you *know*
that you are comparing to zero, and you *must* specify an absolute
tolerance (otherwise it's not a use case at all)?

IIUC, numpy doesn't design APIs this way. They like to have swiss army
knives that can do lots of different things, with lots of flags to request
variant behavior. (I learned this from the discussion about linspace().)
But IMO that goes back to an earlier, murkier tradition -- I recall using
Fortran plot functions in the '80s that had 17 parameters. The reason for
that style was that there was no concept of modules or packages, and hence
there was only one namespace, shared between all possible libraries. So a
new library would claim only a single name in the namespace and hook all
sorts of functionality onto that single name. We don't have that problem in
Python and hence I prefer clarity in functionality -- different functions
for different behaviors, basically. (Maybe this should become the 20th line
of the Zen of Python. :-)


> Still TBD is what the default should be, though.
>
>
>> I still think this is better off as a recipe than as a helper function.
>>>
>>
> Are you prepared to reject the PEP? I'd prefer to give it this one last
> shot at determining if there really is no way to get consensus on a
> good-enough solution. I suspect there is a lot of bike shedding here --
> people have ideas about what is best, and want to understand and talk about
> it, but that doesn't mean that they wouldn't rather see something else that
> nothing. -- that's certainly the case for me (both the bike shedding and
> the desire to see something ;-) )
>

Yes, I am prepared to reject the PEP. In fact any PEP is rejected by
default if no consensus is obtained.


>
> Evidence: The numpy version has its faults -- but it's widely used.
> assertAlmost Equal has even more faults (limitations, anyway) but it's also
> widely used. Boost has something in it, even though it's a one-liner.
> Clearly this is a useful functionality to have available.
>

IIUC Boost's approach is better than numpy. It has separate functions for
is_close (relative) and is_small (absolute), because they are separate use
cases. Its is_close uses the symmetric version (though there is a flag to
choose between weak and strong, which sounds like overkill).


> ChrisA is right -- I have not done a good job at steering the group toward
> a consensus.
>

It's not too late!

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150127/553c2bcf/attachment-0001.html>


More information about the Python-ideas mailing list