time function problem

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Nov 27 19:59:13 EST 2008


On Thu, 27 Nov 2008 11:17:04 -0800, willie wrote:

> My code:
> 
> from time import time
> def leibniz(terms):
> 
> 
>     acc = 0.0
>     num = 4.0 # numerator value remains constant in the series den = 1
>     count = 0
>     start_time = 0.0

This line is wrong. You're starting your timer at the Dawn Of Time, way, 
way back at the Epoch. On my system, the Epoch is:

>>> time.asctime(time.gmtime(0))
'Thu Jan  1 00:00:00 1970'

The right way is to use start_time = time.time().

Now that you have an answer to your direct question, let me suggest 
something different. Currently your function leibniz() does TWO things: 
it calculates the Leibniz value, and it times how long it takes. As a 
general rule, functions should only do ONE thing. You should strip out 
the timing code from the Leibniz code, like this:


from time import time
def leibniz(numterms):
    acc = 0.0
    num = 4.0 # numerator value remains constant in the series
    den = 1
    for aterm in xrange(numterms):
        # (-1) allows fractions to alternate between a + and a - value
        nextterm = num/den  * (-1)**aterm
        acc = acc + nextterm
        den = den + 2
    return acc

def timer(function, arguments):
    start = time.time()
    x = function(arguments)
    timetaken = time.time() - start
    return timetaken

timer(leibniz, 100000)


This risks being inaccurate. The problem is that your computer is multi-
tasking, even if you're not. There's a thousand other processes running 
in the background, and the time they take is included in the time you are 
measuring.

Unfortunately, there's no completely accurate, easy way around that, but 
you can minimize the problem by using the Python timeit module:

http://www.diveintopython.org/performance_tuning/timeit.html

http://www.python.org/doc/2.5.2/lib/module-timeit.html


Here's a trick to help you. The timeit module expects to be given the 
function to be tested as a string, not as a function, but you've already 
written the function once and it is a pain to have to write it again as a 
string. How to work around this? Easy -- instead of using a setup string 
that builds the function from scratch, use a setup string that *imports* 
the function:

from timeit import Timer
# Do a quick test
t = Timer('leibniz(10)', 'from __main__ import leibniz')
print "Best time was: %f seconds", min(t.repeat())/1e6
# Do a long test
t = Timer('leibniz(10000)', 'from __main__ import leibniz')
print "Best time was: %f seconds", min(t.repeat(number=100))/100

On my computer, I get results of about 1e-5 seconds for 10 terms, and 
0.01 seconds for 10,000 terms.



-- 
Steven



More information about the Python-list mailing list