<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jan 8, 2015 at 2:05 PM, Chris Barker <span dir="ltr"><<a href="mailto:chris.barker@noaa.gov" target="_blank">chris.barker@noaa.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>I would think that a floating range class would necessarily use multiplication rather than repeated addition (to allow indexing at arbitrary point), which would avoid cumulative floating-point errors (although it would still have a smaller floating point error at the end), and for the same reason the final value would have to be pre-computed rather than using a naive ">=" which would allow it to be a bit smarter.<br></div></div></div></div></blockquote><div><br></div></span><div>That's the trick -- range() (and arange) does not specify a final value, it specifies a final value not to include. This is well defined and easy to understand for integers, but not so for floating point. But you are right about the multiplication and pre-computing of final value -- that's a good reason to provide this as a built-in -- it's very easy to implement, but even easier to implement badly.</div></div></div></div></blockquote><div><br><br><br>The implementation based on `start + i*step` doesn't solve the 
problem of "unexpected" off-by-one sequences ("unexpected", that is, for
 those not familiar with the vagaries of floating point calculations).<br><br>Suppose frange uses the "half open" convention, and consider<br><br>    frange(start=0.3, stop=0.9, step=0.3)<br><br>With perfect math, it should be [0.3, 0.6]. But check:<br><br>    >>> start = 0.3<br>    >>> stop = 0.9<br>    >>> step = 0.3<br>    >>> [start + i*step for i in range(4) if start + i*step < stop]<br>    [0.3, 0.6, 0.8999999999999999]<br><br>Now suppose frange uses the "closed" convention, and consider<br><br>    frange(start=0.4, stop=1.2, step=0.4)<br><br>Here we naively expect [0.4, 0.8, 1.2].  Take a look at what we get:<br><br>    >>> start = 0.4<br>    >>> stop = 1.2<br>    >>> step = 0.4<br>    >>> [start + i*step for i in range(4) if start + i*step <= stop]<br>    [0.4, 0.8]<br><br>That's because the third value is actually 1.2000000000000002:<br><br>    >>> [start + k*step for k in range(3)]<br>    [0.4, 0.8, 1.2000000000000002]<br><br><br>I've
 fixed at least two bugs in scipy because of exactly this type of naive 
use of numpy's arange function.  The fix is to use np.linspace, as Chris
 explained.  These days, I only use np.arange with integers (or integral
 floating point values);  if I want a uniformally spaced sequence of 
floats with a non-integer step, I use np.linspace.  If I don't want the 
last point, I use the `endpoint=False` argument in `np.linspace` (e.g. 
`x = np.linspace(0, 1, num=4, endpoint=False)` generates [0, 0.25, 0.5, 
0.75]. <br><br></div><div>Warren<br><br></div><div>(Chris, sorry for the duplicate email.  Once again I forgot to "reply all".)<br><br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> But, at least in my own experience, I use arange when I want an interval-based range, and linspace when I want a count-based range.</div></div></div></div></blockquote></span></div></div></div></blockquote><div><br></div></span><div>I would argue (and do!) that you should not do this -- if you know what you are doing with FP, then fine, but it really is tricky. You would be better off computing the count you want then then using linspace anyway. I suppose an interval-based API to something like linspace would be a nice convenience, though.</div><div><br></div><div>I haven't managed to come up with a quick an easy example where this matters, but they DO happen.</div><div><br></div><div>I guess I'm arguing that a range-like object for FP should be a closed rather than open interval -- specifying the starting and end points. That is because defining an open interval where numbers are of finite, but hard to know know in advance the interval, is just too ugly and complex.</div><div><br></div><div>I see your point that sometimes you want a specific delta, and sometimes you want a specific end point, but I supect that most of the time you want a specific delta you ALSO want a specific and point and/or want to know how many values you are going to get. </div><div><br></div><div>In fact, in the most common use of integer range, you really are defining the number of values you want.</div><div><br></div><div>And note that the range convention of starting at zero and not including the stop value was designed to match python indexing convention, i.e.:</div><div><br></div><div>for i in range( len(sequence) ):</div><div>    ...</div><div><br></div><div>is natural an easy to write, and does what's expected. And also:</div><div><br></div><div>for i in range(n):</div><div>    ....</div><div><br></div><div>will loop n times.</div><div><br></div><div>but neither of these apply to floating point ranges.</div><span class=""><font color="#888888"><div><br></div><div>-Chris</div><div><br></div></font></span></div><span class="">-- <br><div><br>Christopher Barker, Ph.D.<br>Oceanographer<br><br>Emergency Response Division<br>NOAA/NOS/OR&R            <a href="tel:%28206%29%20526-6959" value="+12065266959" target="_blank">(206) 526-6959</a>   voice<br>7600 Sand Point Way NE   <a href="tel:%28206%29%20526-6329" value="+12065266329" target="_blank">(206) 526-6329</a>   fax<br>Seattle, WA  98115       <a href="tel:%28206%29%20526-6317" value="+12065266317" target="_blank">(206) 526-6317</a>   main reception<br><br><a href="mailto:Chris.Barker@noaa.gov" target="_blank">Chris.Barker@noaa.gov</a></div>
</span></div></div>
<br>_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/codeofconduct/</a><br></blockquote></div><br></div></div>