bug report: [ #447945 ] time.time() is not non-decreasing

Ken Seehof kseehof at neuralintegrator.com
Sat Aug 4 23:12:45 EDT 2001


import time

class IncreasingTimer:
    def __init__(self):
        trye = 1.0
        self.lasttime=time.time()

        while (self.lasttime + trye) > self.lasttime:
             olde = trye
             trye = trye / 2.0

        # Multiplying by 2.0 once should be enough to deal with the unlikely
        # possibility that time() will increase it's binary order of
magnitude.
        # It is not necessary to do this more than once unless you are
        # planning a continuous run of more than 30 years.  Well, I guess
        # that -could- happen (unless you are using windows).
        # Let's multiply by 4.0.  I'm shy about boundary conditions. :-)

        self._TIME_EPSILON = olde*4.0


    def time(self):
        t = time.time()
        lasttime = self.lasttime

        if t <= lasttime:
            t = lasttime + self._TIME_EPSILON

        self.lasttime = t
        return t

By getting rid of the delta logic, we allow time() to catch up with actual
time, rather than accumulate the error in an increasing delta.

>>> for i in range(20):
...  print t.time() - time.time()
...
0.0
4.76837158203e-007
0.0
4.76837158203e-007
9.53674316406e-007
1.43051147461e-006
1.90734863281e-006
2.38418579102e-006
0.0
4.76837158203e-007
9.53674316406e-007
1.43051147461e-006
1.90734863281e-006
2.38418579102e-006
0.0
4.76837158203e-007
9.53674316406e-007
1.43051147461e-006
1.90734863281e-006
2.38418579102e-006

----- Original Message -----
From: <zooko at zooko.com>
To: "Bruce Sass" <bsass at freenet.edmonton.ab.ca>
Cc: <python-list at python.org>
Sent: Saturday, August 04, 2001 3:53 PM
Subject: Re: bug report: [ #447945 ] time.time() is not non-decreasing


>
> I have committed a cleaned up version of the IncreasingTimer which does
less
> floating point arithmetic and which contains comments showing exactly what
> I don't know about floating point.
>
>
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/mojonation/evil/co
mmon/timeutil.py?content-type=text/plain
>
> The relevant excerpt of the source is appended.
>
> Regards,
>
> Zooko
>
>
> class IncreasingTimer:
>     def __init__(self):
>         self.lasttime = time.time() # This stores the most recent answer
that we returned from `time()'.
>         self.delta = 0 # We add this to the result from the underlying
`time.time()'.
>
>         # How big of an increment do we need to add in order to make the
new float greater than the old float?
>         trye = 1.0
>         while (self.lasttime + trye) > self.lasttime:
>             olde = trye
>             trye = trye / 2.0
>         self._TIME_EPSILON = olde
>
>     def time(self):
>         t = time.time() + self.delta
>         lasttime = self.lasttime
>
>         if t <= lasttime:
>             self.delta = self.delta + (lasttime - t) + self._TIME_EPSILON
>             t = lasttime + self._TIME_EPSILON
>
>         # XXX if you were sure that you could generate a bigger float in
one pass, you could change
>         # this `while' to an `if' and optimize out a test.
>         while t <= lasttime:
>             # We can get into here only if self._TIME_EPSILON is too small
to make the time float "tick over" to a new higher value.
>             # So we (permanently) double self._TIME_EPSILON.
>             # XXX is doubling epsilon the best way to quickly get a
minimally bigger float?
>             self._TIME_EPSILON = self._TIME_EPSILON * 2.0
>             # Delta, having smaller magnitude than t, can be incremented
by more than t was incremented.  (Up to the old epsilon more.)  That's OK.
>             self.delta = self.delta + self._TIME_EPSILON
>             t = t + self._TIME_EPSILON
>
>         self.lasttime = t
>         return t
>
> --
> http://mail.python.org/mailman/listinfo/python-list





More information about the Python-list mailing list