Skip to content

Commit

Permalink
Merge pull request #16480 from JuliaLang/sb/rational
Browse files Browse the repository at this point in the history
Fix rationalize for small values
  • Loading branch information
vtjnash committed May 20, 2016
2 parents 64eb36c + 5c7fd73 commit b45adc5
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
18 changes: 13 additions & 5 deletions base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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) == [
Expand Down

0 comments on commit b45adc5

Please sign in to comment.