# Step

Hi!

I just discovered step, but if I can see (in 1.6) it works on just
integers:(
Is there any reason why it cannot handle floats?

Gergo

±[Kontra, Gergely @ Budapest University of Technology and Economics]-+

``````    Email: kgergely@mcl.hu,  kgergely@turul.eet.bme.hu          |
``````

URL: turul.eet.bme.hu/~kgergely Mobile: (+36 20) 356 9656 |
±------“Olyan langesz vagyok, hogy poroltoval kellene jarnom!”-------+
.
Magyar php mirror es magyar php dokumentacio: http://hu.php.net

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).

···

On Tue, Jun 11, 2002 at 02:42:33AM +0900, Kontra, Gergely wrote:

Hi!

I just discovered step, but if I can see (in 1.6) it works on just
integers:(
Is there any reason why it cannot handle floats?

Gergo

Alan Chen
Digikata LLC
http://digikata.com

Hi,

···

In message “step” on 02/06/11, “Kontra, Gergely” kgergely@mlabdial.hit.bme.hu writes:

I just discovered step, but if I can see (in 1.6) it works on just
integers:(
Is there any reason why it cannot handle floats?

We are experimenting on 1.7.

``````						matz.
``````

“Alan Chen” alan@digikata.com 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