[Python-ideas] Approximately equal operator
Richard Damon
Richard at Damon-Family.org
Fri Jun 15 14:06:26 EDT 2018
On 6/15/18 1:38 PM, Andre Roberge wrote:
> I have a suggestion to make inspired by the current discussion about
> trigonometric functions in degrees, and the desire to have them show
> "exact" values in some special cases.
>
> I suggest that it would be useful to have operators for performing
> **approximate** comparisons. I believe that such operators would be
> useful both for students learning using Python as well as experts
> doing numerical computations.
>
> For discussion purpose, I will use ~= as representing an operator
> testing for approximate equality. (I will show some sample usage below).
>
> When teaching students, the availability of both == and ~= would give
> the opportunity to discuss the fact that numerical computations using
> floats are approximate, while having the possibility to write code
> that is readable using the approximate equality operator instead of
> the strict equality operator when needed.
>
> Before I started writing this email, I had noticed that numpy includes
> at least two functions (isclose and allclose) whose purpose is to
> perform such approximate comparisons. [1] I had completely missed the
> fact that Python added the function isclose() in the math module in
> version 3.5, as described in PEP 485 [0]. I would suggest that the
> possibility of using operators instead of explicit function calls
> could make programs easier to write and read, both for beginners and
> experts alike. I note that PEP 485 makes no mention of introducing
> operators as a possibility.
>
> In addition to an approximate equality operator, it would be natural
> to include two additional operators, greater than or approximately
> equal, and lesser than or approximately equal. These could be written
> respectively as >~= and <~=. I did consider using some relevant utf-8
> symbol instead of combination of ascii characters, but I think that it
> would be easier to write programs if one does not require characters
> nor found on any normal keyboard.
>
> Some time ago, I created a toy module [2] to enable easy experiments
> with some syntactic additions to Python. Using this module, I created
> a very poor and limited implementation that shows what using these
> proposed o[erators might look like [3] ... My current implementation
> is slightly different from either Numpy or Python's math.isclose()
> function [This may no longer be the case soon as I plan to change it
> to use Python's version instead.] . As is the case for isclose(),
> there are two paramaters to be set to determine if the values are
> close enough to be considered approximately equal: an absolute
> tolerance and a relative one. Given that one cannot pass parameters
> to an operator, my implementation includes a function which can change
> the values of these parameters for a given session. If these new
> operators were to be added to Python, such a function would either
> have to be added as a builtin or as a special function in the math module.
>
> Here's a sample session for demonstration purpose...
>
> $ python -m experimental
> experimental console version 0.9.5. [Python version: 3.6.1]
>
> ~~> 0.1 + 0.2
> 0.30000000000000004
> ~~> 0.1 + 0.2 == 0.3
> False
> ~~> from __experimental__ import approx
> ~~> 0.1 + 0.2 ~= 0.3 # use approximately equal operator
> True
> ~~> 0.1 + 0.2 <~= 0.3
> True
> ~~> 0.1 + 0.2 >~= 0.3
> True
> ~~> 2 ** 0.5
> 1.4142135623730951
> ~~> 2**0.5 ~= 1.414
> False
> ~~> set_tols(0.001, 0.001)
> ~~> 2**0.5 ~= 1.414
> True
>
>
> André Roberge
>
> [0] https://www.python.org/dev/peps/pep-0485/
>
> [1] See for
> example https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.isclose.html
>
> [2] https://github.com/aroberge/experimental
>
> [3] https://github.com/aroberge/experimental/blob/master/experimental/transformers/readme.md#approxpy
>
The big issue with 'approximately equals' is that the definition of it
is hard to come up with. This is especially true for small values. In
particular how small does a number need to be to be ~= 0. You also get
inconsistencies, you can have a ~= b, and b ~= c but not a ~= c. You
can have a + b ~= c but not a ~= c - b
should 0.0000001 ~= 0.00000011
To properly handle this sort of thing you need that tolerance parameter,
but the values you give should be carefully though about for THAT
comparison, having a 'global' value is apt to lead to laziness and wrong
answers.
--
Richard Damon
More information about the Python-ideas
mailing list