diff --git a/base/rational.jl b/base/rational.jl index 86bedaac2f404..184e8279672ec 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -111,11 +111,14 @@ function rationalize{T<:Integer}(::Type{T}, x::AbstractFloat; tol::Real=eps(x)) r = x-a y = one(x) - nt, t, tt = tol, zero(tol), zero(tol) + nt, t, tt = tol, zero(tol), tol + # compute the successive convergents of the continued fraction + # np // nq = (p*a + pp) // (q*a + qq) while r > nt try ia = convert(T,a) + np = checked_add(checked_mul(ia,p),pp) nq = checked_add(checked_mul(ia,q),qq) p, pp = np, p @@ -125,16 +128,21 @@ function rationalize{T<:Integer}(::Type{T}, x::AbstractFloat; tol::Real=eps(x)) return p // q end - t, tt = nt, t + # naive approach of using + # x = 1/r; a = trunc(x); r = x - a + # is inexact, so we store x as x/y x, y = y, r - a, r = divrem(x,y) - nt = a*t + tt + + # maintain + # x0 = (p + (-1)^i * r) / q + t, tt = nt, t + nt = a*t+tt end # find optimal semiconvergent # smallest a such that x-a*y < a*t+tt - a = cld(x-tt,y+t) + a = max(cld(x-tt,y+t),0.0) try ia = convert(T,a) np = checked_add(checked_mul(ia,p),pp) diff --git a/test/numbers.jl b/test/numbers.jl index 645c4684074ec..aa2231ba8fcdf 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2131,6 +2131,10 @@ for f in (trunc, round, floor, ceil) 103993//33102 312689//99532 ] +# issue 16311 +rationalize(nextfloat(0.0)) == 0//1 + + # primes @test primes(10000) == primes(2, 10000) == [