Ways to improve this clock algorithm?

J

Jacob H

Hello all,

I'm close to being a novice programmer and I never was good at math.
So I'm curious to know ways in which this following code can be made
more efficient, more elegant. The code just calculates and displays
elapsed wall clock seconds since initialization.

class ExampleTimer:
def __init__(self):
self.start = time.clock()

def run(self):
while 1:
now = time.clock()
allseconds = int(now) = int(self.start)
seconds = 0
minutes = 0
hours = 0
for n in range(1, (allseconds + 1)):
seconds += 1
if n % 60 == 0:
minutes += 1
seconds = 0
if n % 3600 == 0:
hours += 1
minutes = 0
print "%s hrs %s min %s sec" % (hours, minutes, seconds)
time.sleep(1)

app = ExampleTimer()
app.run()

I am grateful for any suggestions and advice. :)

Jake
 
P

Paul Rubin

Hello all,

I'm close to being a novice programmer and I never was good at math.
So I'm curious to know ways in which this following code can be made
more efficient, more elegant. The code just calculates and displays
elapsed wall clock seconds since initialization.

class ExampleTimer:
def __init__(self):
self.start = time.clock()

def run(self):
while 1:
now = time.clock()
allseconds = int(now) = int(self.start)

I think you mean

allseconds = int(now) - int(self.start)

Now you can say

hours = allseconds // 3600
minutes = (allseconds // 60) % 60
seconds = allseconds % 60

instead of counting up to allseconds. You could also use the divmod
function for a fancier way to do the same thing, but the above is
straightforward enough.
 
V

Valentino Volonghi aka Dialtone

I am grateful for any suggestions and advice. :)

import time
class ExampleTimer(object):
def __init__(self):
print "This is my super clock"
self.run()

def run(self):
while 1:
self.update_time()
print "%s hrs %s min %s sec" % (self.hours, self.mins, self.secs)
time.sleep(1)

def update_time(self):
# I would use time.localtime() to update the time because doing this I am
# sure that it is always syncd with my pc time. I think this is the only
# improvement :). It also removes the need for all that math.
self.secs = time.localtime()[5]
self.mins = time.localtime()[4]
self.hours = time.localtime()[3]

app = ExampleTimer()
app.run()
 
J

Jeff Epler

Well, this doesn't run on my system. First, I had to change this line:
now = time.clock()
- allseconds = int(now) = int(self.start)
+ allseconds = int(now) - int(self.start)
seconds = 0
[In all the excerpts, "-" is a line changed/removed from your version,
and "+" is a line changed/added in my version]

Then, I had to insert an 'import':
+ import time
+
class ExampleTimer:
def __init__(self):

Then, this program kept printing "0 hrs 0 min 0 sec", because clock()
returns CPU time (not wall time) on Unix computers. time.time() returns
seconds on all systems Python supports, according to the online
documentation. ("import time; help(time.time)")
def __init__(self):
- self.start = time.clock()
+ self.start = time.time()
- now = time.clock()
+ now = time.time()

Finally, I'm not sure what your 'for n in range ...' code is intended to
do. You can convert the number of seconds into the
hours/minutes/seconds more easily:
# (Replacing the whole 'for' loop and the three asignments above it)
# Take whole minutes and leave the seconds corresponding to the
# fraction of minutes in seconds
minutes = allseconds / 60
seconds = allseconds % 60

# Take whole hours and leave the minutes corresponding to the
# fraction of the hour in minutes
hours = minutes / 60
minutes = minutes % 60
You could do this with the built-in function divmod(), as well:
# (Replacing the whole 'for' loop and the three asignments above it)
minutes, seconds = divmod(allseconds, 60)
hours, minutes = divmod(minutes, 60)

You could test starting at different times by changing init:
- def __init__(self):
- self.start = time.clock()
+ def __init__(self, offset=0):
+ self.start = time.clock() - offset

Now, you can easily see whether the "rollover" to 1 hour works right:
- app = ExampleTimer()
+ app = ExampleTimer(60*60 - 1)
app.run()

Jeff
 
A

Andy Jewell

Hello all,

I'm close to being a novice programmer and I never was good at math.
So I'm curious to know ways in which this following code can be made
more efficient, more elegant. The code just calculates and displays
elapsed wall clock seconds since initialization.

class ExampleTimer:
def __init__(self):
self.start = time.clock()

def run(self):
while 1:
now = time.clock()
allseconds = int(now) = int(self.start)
seconds = 0
minutes = 0
hours = 0
for n in range(1, (allseconds + 1)):
seconds += 1
if n % 60 == 0:
minutes += 1
seconds = 0
if n % 3600 == 0:
hours += 1
minutes = 0
print "%s hrs %s min %s sec" % (hours, minutes, seconds)
time.sleep(1)

app = ExampleTimer()
app.run()

I am grateful for any suggestions and advice. :)

Jake

Jake,

Maybe this'll help:
-andyj
 
B

Bengt Richter

[email protected] (Jacob H) said:
I am grateful for any suggestions and advice. :)

import time
class ExampleTimer(object):
def __init__(self):
print "This is my super clock"
self.run()

def run(self):
while 1:
self.update_time()
print "%s hrs %s min %s sec" % (self.hours, self.mins, self.secs)
time.sleep(1)

def update_time(self):
# I would use time.localtime() to update the time because doing this I am
# sure that it is always syncd with my pc time. I think this is the only
# improvement :). It also removes the need for all that math.
self.secs = time.localtime()[5]
self.mins = time.localtime()[4]
self.hours = time.localtime()[3]
Sooner or later a second will tick between the above statements and give inconsistent h,m,s.
Better to get the tuple, slice it and unpack it, e.g., (untested)

self.hours, self.mins, self.secs = time.localtime()[3:6]

Also, time.sleep(1) will probably span an epsilon more than one second sometime, and
when that hits the second updates right you will get a 2-second hiccup in apparent time
output. As to when it will happen, it's only a matter of time ;-) (Unless you are running
on some platform that has some underlying synchronization with wall clock seconds going on).

One way to get around that might be to sync up with the seconds turnover, either with a
busy wait or with a minimal sleep interval, then sleep say .99 seconds and wait again in
a minimal sleep loop until the second-value changes (if it has not done so already due
to extraneous delays). You can fine tune various aspects of this (as an exercise ;-)

<rant>
This kind of ugliness results if there's no way to tell the OS a precise wall clock time
to ready your process/thread after a wait and/or if timers don't have a way of specifying
accurate intervals that work to the nearest tick and don't accumulate tick resolution errors.
Relatively simple to provide if you are coding the OS clock stuff, so why is application-level
timer expiration usually only relative to a precisely unpredictable "now" instead of a time
coordinate in some time coordinate system?
app = ExampleTimer()
app.run()

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top