no sign() function ?
Steven D'Aprano
steven at REMOVE.THIS.cybersource.com.au
Mon Dec 22 20:48:28 EST 2008
On Mon, 22 Dec 2008 14:51:32 +0100, Pierre-Alain Dorange wrote:
> I'm new to python and here i discover at least 4 methods, i just make a
> small script for timing those methods (100 000 times each on a set of 10
> values).
> I do not use timeit, i can't make it work easyly as it need a standalone
> env for each test.
But that's just what timeit does: it creates a standalone environment for
each test.
> ---- the test script -------------------- #!/usr/bin/env python
>
> from math import atan2
> import time
>
>
> def sign_0(x):
> if x==0.0:
> return 0.0
> elif x>0.0:
> return 1.0
> else:
> return -1.0
>
> def sign_1(x):
> if x > 0 or (x == 0 and atan2(x, -1.) > 0.):
> return 1
> else:
> return -1
>
> def sign_2(x):
> return cmp(x, 0)
>
> sign_3 = lambda x:+(x > 0) or -(x < 0)
>
> def main():
> candidates=[1.1,0.0,-0.0,-1.2,2.4,5.6,-8.2,74.1,-23.4,7945.481]
>
> startTime = time.clock()
time.clock() is low resolution on non-Windows systems. If you are using
Windows, this is okay, if you are not, you are shooting yourself in the
foot.
> for i in range(100000):
> for value in candidates:
Horribly inaccurate, because you are including the time to build a range
of 100,000 integers. In Python 3, that will only be a little bit
inaccurate, but in Python 2.x that will have a MAJOR effect -- possibly
swamping the actual function you are calling.
> s=sign_0(value)
> print "sign_0 : ",time.clock() - startTime
You are (possibly) including the time taken to print to std out in your
time.
> startTime = time.clock()
> for i in range(100000):
> for value in candidates:
> s=sign_1(value)
> print "sign_1 : ",time.clock() - startTime
Repeated code is poor coding practice. Write a function that takes a
function as argument, and call that:
def timer(function, candidates, count=100000):
loop = [None]*count
startTime = time.clock()
for i in loop:
for value in candidates:
s = function(value)
return time.clock() - startTime
But this is just duplicating what timeit already does. Trust me, learn to
use it, you won't be sorry. Here's a trick that took me a long time to
learn: instead of copying your functions into the setup code of timeit,
you can just import them.
This is what I would do (untested):
candidates=[1.1,0.0,-0.0,-1.2,2.4,5.6,-8.2,74.1,-23.4,7945.481]
setup = "from __main__ import sign_%d, candidates"
from timeit import Timer
template = "for x in candidates: s = sign_%d(x)"
for i in range(4):
t = min( Timer(template % i, setup % i).repeat() )
print "Testing sign_%d:" % i, t, "seconds"
> ---- conclusions -------------------------------
None of your conclusions are safe until you have re-tested with a better
timing method. That doesn't mean you are wrong, only that your reasons
for believing them are weak.
--
Steven
More information about the Python-list
mailing list