From: Christoph Date: 2002-06-11T09:59:10+09:00 Subject: Re: step "Alan Chen" wrote in .... > I'm guessing because of the inaccuracy of floats. If you define a step size > smaller then the minimum accuracy of your range, the behavior becomes > undefined. For example if you did: > > 10E9.step(10E10, 10E-9) > > The result would likely be an infinite loop (or maybe an underflow). Actually 1.7 recently introduced steps for Floats - the algorithm is something like class Float Eps = 2.0**(-52) def step(e,s) n = ((e - self) / s + Eps).floor n.times { |i| yield self + i*s } self end end A ``problem'' with this algorithm is that it does not give you an accurate right boundary. For example --- include Math def accurate_right_boundary? (E+3*PI).step(E,-PI) do |i| return true if i == E end false end p accurate_right_boundary? --- will return false. An algorithm by Masaki to adjust the right boundary (the last ``i'') to E (I submitted a slight correction of Masaki algorithm to allow for negative steps) was rejected on the basis that this type of adjustment might be surprising for the user. Anyway the ``adjustment situation'' most likely arises if one wants to subdivide a given interval [a,b] repectively [a,b) into ``n'' equidistant pieces. Since one cannot (in cvs) iterate over Float Ranges anymore (a good thing imo), it is tempting to introduce something like (3.0..7.0).sub_divided(4) { |i| p i } along the lines of class Range def sub_divide(n) # do some kind of argument checking unless first.is_a?(Numeric) && last.is_a?(Numeric) raise "..." end nf = n.to_f unless exclude_end? n.downto(0) do |i| yield first*(i / nf) + last*((n - i)/nf) end else n.downto(1) do |i| yield first*(i / nf) + last*((n - i)/nf) end end self end end (this probably should work differently if Rationals are present). /Christoph