[Tutor] range function and floats?

Steven D'Aprano steve at pearwood.info
Wed Jan 5 12:14:46 CET 2011


Alan Gauld wrote:

>> ...this is more about learning how the range function and floats work 
>> than about writing a super-efficient program.  
> 
> Unfortunately they don't work together.
> 
> range(0.1,0.5,0.1)  -> [0.1,0.2,0.3,0.4]  doesn't work
> you need to do:
> 
> for n in range(1,5):  use( n/10 )


There are pitfalls in writing a range() equivalent for floats. Here's 
one way that doesn't work:


def new_range(start, end, step):
     # DON'T USE THIS!!!
     x = start
     while x < end:
         yield x
         x += step

Here it seems to work:

 >>> list(new_range(5, 10, 0.25))
[5, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5,
7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75]

(Remember that the end argument is excluded!)

But here it fails:


 >>> L = list(new_range(5, 10, 0.1))
 >>> L[-1] == 9.9  # expect the last value to be 9.9
False
 >>> L[-1] == 10.0  # maybe it's 10 then
False

In fact, the last value is a totally unexpected 9.9999999999999822. Such 
is the perils of floating point rounding errors.

I've written a recipe for a float range which I hope avoids as many of 
these problems as possible. It isn't possible to avoid *all* rounding 
error when doing floating point calculation, but this should minimize them:

http://code.activestate.com/recipes/577068-floating-point-range/

As a bonus, it allows you to choose whether the start and end points are 
included or excluded.


-- 
Steven



More information about the Tutor mailing list