Generalized range

Stargaming stargaming at gmail.com
Thu Apr 26 17:45:36 CEST 2007


tkpmep at hotmail.com schrieb:
> I need to create ranges that can start and end with real numbers.
> Searching this newsgroup brought me to a function that I then modified
> as follows:
> 
> def myRange(iMin, iMax=None, iStep=1):
Just as a sidenote: it is not common to prefix your names with its type. 
  It could change at any time and min, max, step would be clear, too. IMO.
>     """Extends range to real numbers. Wherever possible, use Python's
> range .
>        In other cases, make the behavior follow the spirit of Python's
> range """
If you want to stick to the "normal" range-implementation, myRange 
should consider an one-argument-call as transmission of iMax.
>    epsilon = 1.e-8
I can't really say if your attempt using an epsilon-environment is good. 
I think just increasing a "counter" from iMin to iMax should be fine, 
achieving more precision by making computations fuzzy -- i don't know, 
perhaps it's very good. I wouldn't do it.
If you like to care about precision, you should have a look at the 
`decimal module <http://docs.python.org/lib/module-decimal.html>`_.
> 
>     if iMax == None and iStep == 1:
>         return range(int(iMin))
> 
>     elif type(iMin).__name__.lower()  in ('int', 'long') and \
>          type(iMax).__name__.lower()  in ('int', 'long') and \
>          type(iStep).__name__.lower() in ('int', 'long') and iStep !=
> 0:
>         return range( iMin, iMax, iStep)
Ouchie! *That* is a bad one. Checking for a name of an object is neither 
safe nor good nor common. A better way would be directly comparing 
type(yourobject) with int/long/float/anytype. See 
http://docs.python.org/lib/comparisons.html for details on comparisons.
Another way of type-checking in python is doing something like ``if 
isinstance(iMin, (int, long))``. Would work for subclasses, too.
> 
>     elif iMin <= iMax and iStep > 0:
>         return [ iMin+i*iStep for i in range( int(math.ceil((iMax -
> iMin - epsilon)/iStep)) )]
> 
>     elif iMin >= iMax and iStep < 0:
>         return [ iMin+i*iStep for i in range(-int(math.ceil((iMin -
> iMax + epsilon)/iStep)) )]
> 
Will eat your memory. See below.
>     else:
>         raise ValueError, 'Cannot construct a range with steps of size
> ' + str(iStep) + ' between ' + str(iMin) + ' and ' + str(iMax)
In Python, it is common to use string interpolation instead. Like::
   print 'Hello from %d to %d' % (iMin, iMax)
Read `String Formatting Operations 
<http://docs.python.org/lib/typesseq-strings.html>`_ in the manual for 
details.
> 
> 
> The one part of  my implementation that has me a bit queasy (i.e.
> works in my current application, but I can see it misbehaving
> elsewhere) is the addition/subtraction of a fixed epsilon to ensure
> that my rounding goes the right way. A clean implementation would
> modify epsilon based on the achievable level of precision given the
> particular values of iMax, iMin and iStep. I suspect this requires a
> detailed understanding of the implementation of floating point
> arithmetic, 
I think so, too. That's why it is a bad idea, IMO.
> and would appreciate hearing any thoughts you might have
> on gilding this lily.
> 
> Sincerely
> 
> Thomas Philips
> 

I'd recommend you to have a look into `generators 
<http://docs.python.org/ref/yield.html>`_, it is what `xrange 
<http://docs.python.org/lib/built-in-funcs.html#l2h-80>`_ uses. You 
don't put all numbers into your memory ("precompute them") but behave a 
little bit lazy and compute them whenever the user needs the next one. I 
expect Google to have lots of example implementations of range as a 
generator in python for you. :-)

HTH,
Stargaming



More information about the Python-list mailing list