[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