[Tutor] range() fractional increment

Lie Ryan lie.1296 at gmail.com
Tue Mar 31 07:27:58 CEST 2009


John Fouhy wrote:
> 2009/3/31 james carnell <jimcarnell at yahoo.com>:
>> for row in range(25,31,1):
>>     for col in range(10,12, 0.3):  #<- Crash Bang doesn't work 0.3 = zero =
>> infinite loop?
>> [...]
>> is there no way to do it with a range function (and have it still look like
>> you're not on crack)?
> 
> Well, you could do this:
> 
>>>> [float(x)/3 for x in range(30, 37)]
> [10.0, 10.333333333333334, 10.666666666666666, 11.0,
> 11.333333333333334, 11.666666666666666, 12.0]
> 
> Or even:
> 
>>>> [math.floor(10*float(x)/3)/10 for x in range(30, 37)]
> [10.0, 10.300000000000001, 10.6, 11.0, 11.300000000000001, 11.6, 12.0]
> 
> However, the builtin range() only works with integers.  I think there
> is a range() function in the python cookbook that will do fractional
> step sizes.
> 
> But really, there's nothing wrong with your while loop.
> 

You could boil your own range function (beware: binary floating point 
may be imprecise)

def frange(start, stop, step):
     width = stop - start
     n = round(width / step)
     return [start + step*i for i in xrange(n)]

or returning generator instead (may be preferable if the size of the 
list is extremely large):

def frange(start, stop, step):
     width = stop - start
     n = round(width / step)
     return (start + step*i for i in xrange(n))

slightly obscured version:

def frange(start, stop, step):
     return (start + step*i for i in range(round((stop - start) / step)))

more complex homebrew frange may return a class that really emulates 
xrange, by implementing __getitem__, iterator protocol, generator 
protocol, and all the sugar without ever creating a real list.



More information about the Tutor mailing list