sort() comparison lambda for floats/longs

Jack Diederich jack_diederich at email.com
Mon Jul 29 21:49:29 EDT 2002


[sorry if this appears unthreaded, I don't subscribe to the list]

> here is a lambda I am using in a list.sort()
> delta_cmp = [big lambda with lots of ors and ands]

:Brrrrrr.  Throw that away before it breeds <wink>.

good point, already forgotten

:def delta_cmp(a, b, delta=0.00001):
:    if abs(a-b) < delta:
:        return 0
:    else:
:        return cmp(a, b)
:
:does the same thing, but without trickery.  Note that 
:there's nothing magical about a lambda expression -- it's 
:exactly the same as a named
:function except for lacking a name <wink>, and .sort() 
:couldn't care less whether you pass it a lambda expression
:or the name of a comparison
:function.  The runtime is the same either way too.

True, I just did some benchmarks and the same contents put
into a func and a lambda were almost identically fast.
The lambda won by a couple percent, but that could be for
almost any reason in my make-shift test.

But the lambda can't have if/else statements in it, and
versions of the delta compare with if/else statements killed
the nested 'and' 'or' versions by %33 - %50
So if you need an if else, use a func and not a lambda

I did find one please-explain-it-to-me result,

this
def func1(a,b,delta=0.00001):
  if (abs(a-b) < delta):
    return 0
  elif(a > b):
    return 1
  else:
    return -1

is %20 faster than 
def func2(a, b, delta=0.00001):
    if abs(a-b) < delta:
        return 0
    else:
        return cmp(a, b)

which is odd. replacing the cmp() call in func2
to float.__cmp__ just makes it a lot worse.  replacing
the cmp() call to be a variable equal to float.__cmp__
is better than float.__cmp__ but still stinky

benchmarks in wall seconds for sorting 0.0 .. 3000.0
in order is

func1 : 4.1 sec
func2 : 5.5 sec
func2b: 8.0 sec (replace cmp w/ float.__cmp__)
func2c: 6.7 sec (replace cmp w/ foo, where 
                 foo = float.__cmp__)

it isn't a great test, the numbers are in a list that
is already sorted. I sorted 10 times with each func
on a pIII 400MHz.  So these numbers are interesting but
not scientific.

I assume the float.__cmp__ is looking up __cmp__ in float's
dict for every comparison, so that being slow makes sense.

the if/elif/else version (func1) is still faster even if
we do the sort in the other direction, so it isn't just
that the more heavilly used branch is earlier.  cmp() might
be spending some time figuring out what to compare to what,
but the elif (a > b) would have to do the same thing.


So I have three questions:
1) anyone know why func1 is faster than func2?
2) is there ever a reason to use a lambda other than for
   run-time generated code (and then why is it better than
   an eval)?
3) I'll ask in a seperate post why the output of
   a = [1.0 + 0.1]
   print a, a[0]
   --- output ---
   [1.1000000000000001] 1.1
   should[n't] scare the crap out of me

thanks again,

-jackdied

-- 
__________________________________________________________
Sign-up for your own FREE Personalized E-mail at Mail.com
http://www.mail.com/?sr=signup

Get 4 DVDs for $.49 cents! plus shipping & processing. Click to join.
http://adfarm.mediaplex.com/ad/ck/990-1736-3566-59





More information about the Python-list mailing list