Skip to content

rationalize(x::Rational) inconsistencies #60768

@lvlte

Description

@lvlte
julia> x = float(pi)
3.141592653589793

julia> r = rationalize(x)
165707065//52746197

julia> rationalize(r, tol=0.1)               # tol is ignored
165707065//52746197

julia> rationalize(Int, r, tol=0.1)         
ERROR: OverflowError: 7468474 * 36028797018963968 overflowed for type Int64
Stacktrace:
 [1] throw_overflowerr_binaryop(op::Symbol, x::Int64, y::Int64)
   @ Base.Checked .\checked.jl:163
 [2] checked_mul
   @ .\checked.jl:297 [inlined]
 [3] +
   @ .\rational.jl:362 [inlined]
 [4] rationalize(::Type{Int64}, x::Rational{Int64}, tol::Float64)
   @ Base .\rational.jl:262
 [5] #rationalize#247
   @ .\rational.jl:277 [inlined]
 [6] top-level scope
   @ REPL[64]:1

julia> rationalize(Int, r, tol=0.0)
165707065//52746197

julia> rationalize(Int, big(r), tol=0.1)
16//5

We shouldn't need big(r) to reduce the precision of r.

I noticed rationalize has a single method for x::Union{AbstractFloat, Rational}. When x is a rational, the error term and tolerance term of the convergents of r (and other variables used in the function) are also rationals, and as those terms approach zero, their denominator are very likely to overflow even with a relatively large tolerance. Actually the function was written for floats (they can represent smaller values with the same precision, whereas rational components would need more). Support for rational were added in #43427.

Metadata

Metadata

Assignees

No one assigned

    Labels

    mathsMathematical functionsrationalsThe Rational type and values thereof

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions