Skip to content

Commit 8a1b642

Browse files
tantheta01JeffBezansonoscardssmith
authored
Add method to rationalize Rational (#43427)
* Add Method to Rationalize Rational and Integer Co-authored-by: Jeff Bezanson <[email protected]> Co-authored-by: Oscar Smith <[email protected]>
1 parent 03c4bc1 commit 8a1b642

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

base/rational.jl

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,11 @@ julia> typeof(numerator(a))
173173
BigInt
174174
```
175175
"""
176-
function rationalize(::Type{T}, x::AbstractFloat, tol::Real) where T<:Integer
176+
function rationalize(::Type{T}, x::Union{AbstractFloat, Rational}, tol::Real) where T<:Integer
177177
if tol < 0
178178
throw(ArgumentError("negative tolerance $tol"))
179179
end
180+
180181
T<:Unsigned && x < 0 && __throw_negate_unsigned()
181182
isnan(x) && return T(x)//one(T)
182183
isinf(x) && return unsafe_rational(x < 0 ? -one(T) : one(T), zero(T))
@@ -188,7 +189,6 @@ function rationalize(::Type{T}, x::AbstractFloat, tol::Real) where T<:Integer
188189
a = trunc(x)
189190
r = x-a
190191
y = one(x)
191-
192192
tolx = oftype(x, tol)
193193
nt, t, tt = tolx, zero(tolx), tolx
194194
ia = np = nq = zero(T)
@@ -233,10 +233,21 @@ function rationalize(::Type{T}, x::AbstractFloat, tol::Real) where T<:Integer
233233
return p // q
234234
end
235235
end
236-
rationalize(::Type{T}, x::AbstractFloat; tol::Real = eps(x)) where {T<:Integer} = rationalize(T, x, tol)::Rational{T}
236+
rationalize(::Type{T}, x::AbstractFloat; tol::Real = eps(x)) where {T<:Integer} = rationalize(T, x, tol)
237237
rationalize(x::AbstractFloat; kvs...) = rationalize(Int, x; kvs...)
238-
rationalize(::Type{T}, x::Complex; kvs...) where {T<:Integer} = Complex(rationalize(T, x.re, kvs...)::Rational{T}, rationalize(T, x.im, kvs...)::Rational{T})
239-
rationalize(x::Complex; kvs...) = Complex(rationalize(Int, x.re, kvs...), rationalize(Int, x.im, kvs...))
238+
rationalize(::Type{T}, x::Complex; kvs...) where {T<:Integer} = Complex(rationalize(T, x.re; kvs...), rationalize(T, x.im; kvs...))
239+
rationalize(x::Complex; kvs...) = Complex(rationalize(Int, x.re; kvs...), rationalize(Int, x.im; kvs...))
240+
rationalize(::Type{T}, x::Rational; tol::Real = 0) where {T<:Integer} = rationalize(T, x, tol)
241+
rationalize(x::Rational; kvs...) = x
242+
rationalize(x::Integer; kvs...) = Rational(x)
243+
function rationalize(::Type{T}, x::Integer; kvs...) where {T<:Integer}
244+
if Base.hastypemax(T) # BigInt doesn't
245+
x < typemin(T) && return unsafe_rational(-one(T), zero(T))
246+
x > typemax(T) && return unsafe_rational(one(T), zero(T))
247+
end
248+
return Rational{T}(x)
249+
end
250+
240251

241252
"""
242253
numerator(x)

test/rational.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ using Test
3333

3434
@test @inferred(rationalize(Int, 3.0, 0.0)) === 3//1
3535
@test @inferred(rationalize(Int, 3.0, 0)) === 3//1
36+
@test @inferred(rationalize(Int, 33//100; tol=0.1)) === 1//3 # because tol
37+
@test @inferred(rationalize(Int, 3; tol=0.0)) === 3//1
38+
@test @inferred(rationalize(Int8, 1000//333)) === Rational{Int8}(3//1)
39+
@test @inferred(rationalize(Int8, 1000//3)) === Rational{Int8}(1//0)
40+
@test @inferred(rationalize(Int8, 1000)) === Rational{Int8}(1//0)
3641
@test_throws OverflowError rationalize(UInt, -2.0)
3742
@test_throws ArgumentError rationalize(Int, big(3.0), -1.)
3843
# issue 26823
@@ -727,3 +732,10 @@ end
727732
@test rationalize(1.192 + 2.233im) == 149//125 + 2233//1000*im
728733
@test rationalize(Int8, 1.192 + 2.233im) == 118//99 + 67//30*im
729734
end
735+
@testset "rationalize(Complex) with tol" begin
736+
# test: rationalize(x::Complex; kvs...)
737+
precise_next = 7205759403792795//72057594037927936
738+
@assert Float64(precise_next) == nextfloat(0.1)
739+
@test rationalize(nextfloat(0.1) * im; tol=0) == precise_next * im
740+
@test rationalize(0.1im; tol=eps(0.1)) == rationalize(0.1im)
741+
end

0 commit comments

Comments
 (0)