[Python-Dev] math.areclose ...?

Smith smiles at worksmail.net
Wed Feb 15 15:29:01 CET 2006

```A problem that I pointed out with the proposed areclose() function is that it has within it a fp comparison. If such a function is to have greater utility, it should allow the user to specify how significant to consider the computed error. A natural extension of being able to tell if 2 fp numbers are close is to make a more general comparison. For that purpose, a proposed fpcmp function is appended. From that, fp boolean comparison operators (le, gt, ...) are easily constructed.

Python allows fp comparison. This is significantly of source of surprises and learning experiences. Are any of these proposals of interest for providing tools to more intelligently make the fp comparisons?

###
#new proposal for the areclose() function
def areclose(x,y,atol=1e-8,rtol=1e-5,prec=12):
"""Return False if the |x-y| is greater than atol or
greater than the absolute value of the larger of x and y,
otherwise True. The comparison is made by computing a
difference that should be 0 if the two numbers satisfy
either condition; prec controls the precision of the
value that is obtained, e.g. 8.3__e-17 is obtained
for (2.1-2)-.1. But rounding to the 12th digit (the default
precision) the value of 0.0 is returned indicating that for
that precision there is no (significant) error."""

diff = abs(x-y)
return round(diff-atol,prec)<=0 or \
round(diff-rtol*max(abs(x),abs(y)),prec)<=0

#fp cmp
def fpcmp(x,y,atol=1e-8,rtol=1e-5,prec=12):
"""Return 0 if x and y are close in the absolute or
relative sense. If not, then return -1 if x < y or +1 if x > y.
Note: prec controls how many digits of the error are retained
when checking for closeness."""

if areclose(x,y,atol,rtol,prec):
return 0
else:
return cmp(x,y)

# fp comparisons functions
def lt(x,y,atol=1e-8,rtol=1e-5,prec=12):
return fpcmp(x, y, atol, rtol, prec)==-1
def le(x,y,atol=1e-8,rtol=1e-5,prec=12):
return fpcmp(x, y, atol, rtol, prec) in (-1,0)
def eq(x,y,atol=1e-8,rtol=1e-5,prec=12):
return fpcmp(x, y, atol, rtol, prec)==0
def gt(x,y,atol=1e-8,rtol=1e-5,prec=12):
return fpcmp(x, y, atol, rtol, prec)==1
def ge(x,y,atol=1e-8,rtol=1e-5,prec=12):
return fpcmp(x, y, atol, rtol, prec) in (0,1)
def ne(x,y,atol=1e-8,rtol=1e-5,prec=12):
return fpcmp(x, y, atol, rtol, prec)<>0
###
```