Step


(KONTRA Gergely) #1

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


(Alan Chen) #2

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


(Yukihiro Matsumoto) #3

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.

(Christoph) #4

“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) inton’’ 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