-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
fix spurious overflow for Float16(::Rational) #52395
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
Changes from all commits
fe92f1d
e4d8979
b24c5ca
6aab59b
ce4b622
c34a75d
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 |
|---|---|---|
|
|
@@ -145,6 +145,14 @@ function (::Type{T})(x::Rational{S}) where T<:AbstractFloat where S | |
| P = promote_type(T,S) | ||
| convert(T, convert(P,x.num)/convert(P,x.den))::T | ||
| end | ||
| # avoid spurious overflow (#52394). (Needed for UInt16 or larger; | ||
| # we also include Int16 for consistency of accuracy.) | ||
| Float16(x::Rational{<:Union{Int16,Int32,Int64,UInt16,UInt32,UInt64}}) = | ||
| Float16(Float32(x)) | ||
| Float16(x::Rational{<:Union{Int128,UInt128}}) = | ||
| Float16(Float64(x)) # UInt128 overflows Float32, include Int128 for consistency | ||
| Float32(x::Rational{<:Union{Int128,UInt128}}) = | ||
| Float32(Float64(x)) # UInt128 overflows Float32, include Int128 for consistency | ||
|
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. Wouldn't these suffer from double-rounding accuracy loss? @oscardssmith 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. they would. Doing this properly is fairly hard though. 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. Also worth noting that 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. Question is: is this problem worse than the problem this PR fixes? I.e. should we merge and improve this later, or should this wait until this PR does it "right" (whatever that means?) 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 should merge and improve later. 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. That was my thought as well, but want to confirm. 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. Would doing it "properly" be something like: a = Float64(x)
b = Float32(a)
# check if we double-rounded in the wrong direction
if x > a && b < a && nextfloat(b) < a
b = nextfloat(b)
elseif x < a && b > a && prevfloat(b) > a
b = prevfloat(b)
end
return bThere 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. A example of a test case where double rounding gives a different result is: julia> r = 12928845309018111//18014398509481984
12928845309018111//18014398509481984
julia> Float32(r) == Float32(Float64(r))
false@vtjnash's code doesn't fix this, however — its output matches (Example constructed by tweaking a number almost exactly halfway between two |
||
|
|
||
| function Rational{T}(x::AbstractFloat) where T<:Integer | ||
| r = rationalize(T, x, tol=0) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.