[SciPy-user] Problem with arange

Fernando Perez fperez at colorado.edu
Thu Nov 6 01:49:51 EST 2003


Lance Boyle wrote:
> This kind of floating point issue is present in some form on any 
> platform and language. However, Numeric.arange() makes it possible to 
> "automate" the error. <Flamebait> A language with ambitions to be a 
> numerical computing platform should not make it this easy. 
> Numeric.arange() is a dangerous function and should be eliminated.
> 
> Bottom line: Don't use it unless you know without a doubt that your 
> "epsilon" will always work.

Flamebait aside, here's the implementation I use for my own work, which is 
part of ipython.  After this thread I noticed my original frange() had the 
same problem as arange(), but because of the way it's written, it was trivial 
to fix.  I guess I prefer to fix a useful function which has a problem rather 
than eliminating every piece of code which isn't perfect.

Feel free to use it if you like, or if you already use ipython, it's in 
IPython.numutils.

Note that my frange defaults to CLOSED intervals, because that's how I tend to 
use it most (in fact, I use the npts=N option ~100% of the time).  For 
plotting, I typically want the endpoints included.  But you can set the 
default to open trivially by modifying one line below.


def frange(xini,xfin=None,delta=None,**kw):
     """frange([start,] stop[, step, keywords]) -> list of floats

     Return a Numeric array() containing a progression of floats. Similar to
     arange(), but defaults to a closed interval.

     frange(x0, x1) returns [x0, x0+1, x0+2, ..., x1]; start defaults to 0, and
     the endpoint *is included*. This behavior is different from that of
     range() and arange(). This is deliberate, since frange will probably be
     more useful for generating lists of points for function evaluation, and
     endpoints are often desired in this use. The usual behavior of range() can
     be obtained by setting the keyword 'closed=0', in this case frange()
     basically becomes arange().

     When step is given, it specifies the increment (or decrement). All
     arguments can be floating point numbers.

     frange(x0,x1,d) returns [x0,x0+d,x0+2d,...,xfin] where xfin<=x1.

     frange can also be called with the keyword 'npts'. This sets the number of
     points the list should contain (and overrides the value 'step' might have
     been given). arange() doesn't offer this option.

     Examples:
     >>> frange(3)
     array([ 0.,  1.,  2.,  3.])
     >>> frange(3,closed=0)
     array([ 0.,  1.,  2.])
     >>> frange(1,6,2)
     array([1, 3, 5])
     >>> frange(1,6.5,npts=5)
     array([ 1.   ,  2.375,  3.75 ,  5.125,  6.5  ])
     """

     #defaults
     kw.setdefault('closed',1)
     endpoint = kw['closed'] != 0

     # funny logic to allow the *first* argument to be optional (like range())
     # This was modified with a simpler version from a similar frange() found
     # at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66472
     if xfin == None:
         xfin = xini + 0.0
         xini = 0.0

     if delta == None:
         delta = 1.0

     # compute # of points, spacing and return final list
     try:
         npts=kw['npts']
         delta=(xfin-xini)/float(npts-endpoint)
     except KeyError:
         # round() gets npts right even with the vagaries of floating point.
         npts=int(round((xfin-xini)/delta+endpoint))

     return arange(npts)*delta+xini


Cheers,

f.



More information about the SciPy-User mailing list