Short-circuit Logic

Carlos Nepomuceno carlosnepomuceno at outlook.com
Thu May 30 17:03:13 EDT 2013


----------------------------------------
> From: steve+comp.lang.python at pearwood.info
> Subject: Re: Short-circuit Logic
> Date: Thu, 30 May 2013 05:42:17 +0000
> To: python-list at python.org
[...]
> Here's another way, mathematically equivalent (although not necessarily
> equivalent using floating point computations!) which avoids the divide-by-
> zero problem:
>
> abs(a - b) < epsilon*a

That's wrong! If abs(a) < abs(a-b)/epsilon you will break the commutative law. For example:

import sys
eps = sys.float_info.epsilon
def almost_equalSD(a,b):
    return abs(a-b) < eps*a

#special case
a=1
b=1/(1-eps)
almost_equalSD(a,b) == almost_equalSD(b,a)

Returns False.

This discussion reminded me of TAOCP and I paid a visit and bring the following functions:


#Floating Point Comparison Operations
#Knuth, Donald (1981). The Art of Computer Programming. 2nd ed. Vol. 2. p. 218. Addison-Wesley. ISBN 0-201-03822-6.
import sys

#floating point comparison: u ≺ v(ε) "definitely less than" (definition 21)
def fpc_dlt(u,v,eps=sys.float_info.epsilon):
    au=abs(u)
    av=abs(v)
    return (v-u)> (eps*(au if au>av else av))  # v-u> ε*max(|u|,|v|)

#floating point comparison: u ~ v(ε) "approximately equal to" (definition 22)
def fpc_aeq(u,v,eps=sys.float_info.epsilon):
    au=abs(u)
    av=abs(v)
    return abs(v-u) <= (eps*(au if au>av else av))  # |v-u| <= ε*max(|u|,|v|)

#floating point comparison: u ≻ v(ε) "definitely greater than" (definition 23)
def fpc_dgt(u,v,eps=sys.float_info.epsilon):
    au=abs(u)
    av=abs(v)
    return (u-v)> (eps*(au if au>av else av))  # u-v> ε*max(|u|,|v|)

#floating point comparison: u ≈ v(ε) "essentially equal to" (definition 24)
def fpc_eeq(u,v,eps=sys.float_info.epsilon):
    au=abs(u)
    av=abs(v)
    return abs(v-u) <= (eps*(au if au<av else av))  # |v-u| <= ε*min(|u|,|v|)


I've tried to make it look a bit pythonic. Please let me know if it can be improved. ;)

So, if you try the following you get the correct answer:

#special case
a=1
b=1/(1-eps)
fpc_aeq(a,b) == fpc_aeq(b,a)


>
> Whichever method you choose, there are gotchas to watch out for.
>
>> http://xkcd.com/1047/
>
> Nice!
>
>
> --
> Steven
> --
> http://mail.python.org/mailman/listinfo/python-list 		 	   		  


More information about the Python-list mailing list