[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
###


More information about the Python-Dev mailing list