-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Fix rationalize([T,] x::Rational; ...)
#61057
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
82771ec
bd0aa6f
13c4031
a797f5a
9dec955
746b5c8
768dd9c
2b0cfe2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -244,11 +244,8 @@ julia> typeof(numerator(a)) | |
| BigInt | ||
| ``` | ||
| """ | ||
| function rationalize(::Type{T}, x::Union{AbstractFloat, Rational}, tol::Real) where T<:Integer | ||
| if tol < 0 | ||
| throw(ArgumentError("negative tolerance $tol")) | ||
| end | ||
|
|
||
| function rationalize(::Type{T}, x::AbstractFloat, tol::Real) where T<:Integer | ||
| tol < 0 && throw(ArgumentError("Tolerance can not be negative. tol=$tol")) | ||
| T<:Unsigned && x < 0 && __throw_negate_unsigned() | ||
| isnan(x) && return T(x)//one(T) | ||
| isinf(x) && return unsafe_rational(x < 0 ? -one(T) : one(T), zero(T)) | ||
|
|
@@ -257,9 +254,8 @@ function rationalize(::Type{T}, x::Union{AbstractFloat, Rational}, tol::Real) wh | |
| pp, qq = zero(T), one(T) | ||
|
|
||
| x = abs(x) | ||
| a = trunc(x) | ||
| r = x-a | ||
| y = one(x) | ||
| r, a = modf(x) | ||
| tolx = oftype(x, tol) | ||
| nt, t, tt = tolx, zero(tolx), tolx | ||
| ia = np = nq = zero(T) | ||
|
|
@@ -309,7 +305,18 @@ rationalize(x::Real; kvs...) = rationalize(Int, x; kvs...) | |
| rationalize(::Type{T}, x::Complex; kvs...) where {T<:Integer} = Complex(rationalize(T, x.re; kvs...), rationalize(T, x.im; kvs...)) | ||
| rationalize(x::Complex; kvs...) = Complex(rationalize(Int, x.re; kvs...), rationalize(Int, x.im; kvs...)) | ||
| rationalize(::Type{T}, x::Rational; tol::Real = 0) where {T<:Integer} = rationalize(T, x, tol) | ||
| rationalize(x::Rational; kvs...) = x | ||
| rationalize(x::Rational{T}; kvs...) where {T<:Integer} = rationalize(T, x; kvs...) | ||
| function rationalize(::Type{T}, x::Rational, tol::Real) where {T<:Integer} | ||
| T<:Unsigned && x < 0 && __throw_negate_unsigned() | ||
| if 0 ≤ tol ≤ eps(float(x)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technically I guess if although I don't think
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can do : if 0 ≤ tol ≤ eps(float(x)) || isinf(float(x))
try
return Rational{T}(x)
catch e
isa(e,InexactError) || rethrow()
end
end
return rationalize(T, float(x), tol)If |
||
| try | ||
| return Rational{T}(x) | ||
| catch e | ||
| isa(e,InexactError) || rethrow() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the InexactError might come from tol=0, but we want that to rethrow as well right? since float(x) may lose precision and the fallback won't end up throwing.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure, I did this to be consistent with the general behavior of This brings us to #52335
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can still do
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact no.. the problem is that until now we have this behavior : julia> r = 2616549525268589//9223372036854775807
2616549525268589//9223372036854775807
julia> Rational{Int32}(r)
ERROR: InexactError: trunc(Int32, 2616549525268589) [...]
julia> rationalize(Int32, r) # <- default `tol` is zero
330434//1164784265 # <- loss of precisionAnd this is probably the expected behavior for most users calling
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can tolerate that :) I totally agree, rationalize(::Type{T}, x::Rational; tol::Real = 1/typemax(T)) where {T<:Integer} = rationalize(T, x, tol)
rationalize(x::Rational{T}; kvs...) where {T<:Integer} = rationalize(T, x; kvs...)
function rationalize(::Type{T}, x::Rational, tol::Real) where {T<:Integer}
T<:Unsigned && x < 0 && __throw_negate_unsigned()
if 0 ≤ tol ≤ eps(float(x)) || isinf(float(x))
return Rational{T}(x)
end
return rationalize(T, float(x), tol)
endAh and we would need a specific default tolerance for
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok I will push that tomorrow |
||
| end | ||
| end | ||
| return rationalize(T, float(x), tol) | ||
| end | ||
| rationalize(x::Integer; kvs...) = Rational(x) | ||
| function rationalize(::Type{T}, x::Integer; kvs...) where {T<:Integer} | ||
| if Base.hastypemax(T) # BigInt doesn't | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.