Skip to content
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

parse(Rational{Int},string) #18328

Closed
cossio opened this issue Sep 1, 2016 · 16 comments
Closed

parse(Rational{Int},string) #18328

cossio opened this issue Sep 1, 2016 · 16 comments
Labels
domain:rationals The Rational type and values thereof

Comments

@cossio
Copy link
Contributor

cossio commented Sep 1, 2016

Currently parse(Rational{Int}, string) is not implemented. I think it could be implemented like this:

function Base.parse(::Type{Rational{Int}}, x::ASCIIString)
    ms, ns = split(x, '/', keep=false)
    m = parse(Int, ms)
    n = parse(Int, ns)
    return m//n
end

Base.parse(::Type{Rational}, x::ASCIIString) = parse(::Type{Rational{Int}}, x)
@TotalVerb
Copy link
Contributor

One might also consider supporting parsing decimals this way.

@oxinabox
Copy link
Contributor

oxinabox commented Sep 2, 2016

Related to this (re: @TotalVerb):

@Ismael-VC and I came up with this a while ago, for parsing decimal literals exactly:

macro R_str(str)
  if contains(str, ".")
    whole, frac = split(str, ".")
    frac = rstrip(frac,['0'])
    numer = parse(whole * frac) #Append
    denom_exp = length(frac)
    denom = :((10*one(typeof($numer)))^$denom_exp)
    :(Rational($numer, $denom))
  else
      :(Rational(parse($str), 1))
  end
end

julia> a = R"100.3"
1003//10

julia> typeof(a)
Rational{Int64}

julia> Float64(a)
100.3

julia> b = R"922337203685.4775809"
9223372036854775809//10000000

julia> typeof(b)
Rational{Int128}

julia> Float64(b)
9.223372036854775e11

@TotalVerb
Copy link
Contributor

This is a good start, but I don't think it handles the cases where the denominator overflows but the whole number can still fit in a Rational{Int}. Also would be nice to handle e/E as well.

@TotalVerb
Copy link
Contributor

TotalVerb commented Sep 2, 2016

As an example:

julia> R"0.0000000000000000005"
-5//8446744073709551616

I suspect it will be easier (if maybe slightly less performant) to parse as Rational{BigInt} and convert later. A hypothetical @R_str macro should return Rational{BigInt} anyway.

@ivarne
Copy link
Sponsor Member

ivarne commented Sep 2, 2016

A hypothetical @R_str macro should return Rational{BigInt} anyway.

A macro don't have to be type stable for performance. It is evaluated before type infrerence.

@TotalVerb
Copy link
Contributor

@ivarne It's not a matter of performance. I suspect most use cases for Rational are for exact arithmetic, and BigInt makes more sense.

@cossio
Copy link
Contributor Author

cossio commented Sep 2, 2016

I made some improvements, to account for the fact that the parsed string could be an integer (like "1", with no "/" character), and allowing BigInts.

function Base.parse{T<:Integer}(::Type{Rational{T}}, x::ASCIIString)
    list = split(x, '/', keep=false)
    if length(list) == 1
        return parse(T, list[1]) // 1
    else
        @assert length(list) == 2
        return parse(T, list[1]) // parse(T, list[2])
    end
end

@henriquebecker91
Copy link
Contributor

There is something blocking this? Today I was surprised by the lack of a parse for Rational and had to wrote a simple implementation.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Mar 10, 2022

Looks like nobody has particularly tried. Care to make a PR? There seems to be several possible drafts above

@cossio
Copy link
Contributor Author

cossio commented Mar 10, 2022

Updated version of the code I posted above for Julia 1:

function Base.parse(::Type{Rational{T}}, x::AbstractString) where {T<:Integer}
    list = split(x, '/'; keepempty=false)
    if length(list) == 1
        return parse(T, list[1]) // 1
    else
        @assert length(list) == 2
        return parse(T, list[1]) // parse(T, list[2])
    end
end

But note the following issues:

julia> parse(Rational{Int}, "1/2")
1//2

julia> parse(Rational{Int}, "1//2")
1//2

julia> parse(Rational{Int}, "1///2")
1//2

julia> string(1//2)
"1//2"

Should we parse "1/2"? Or restrict to only accept "1//2"?

@henriquebecker91
Copy link
Contributor

Can do it, probably, I just need to know if splitting over '/' is reasonable, or there some special notation case I should consider. I believe implementing a generic method Base.parse(::Type{Rational{T}}, x::AbstractString) where {T <: Integer} is the way to go, but I am unsure if we should restrict T to Integer, or instead either restrict it to Number or not restrict it.

@henriquebecker91
Copy link
Contributor

We can use split("1//2", "//") if a single '/' should not be considered valid.

@cossio
Copy link
Contributor Author

cossio commented Mar 10, 2022

T has to be <:Integer:

julia> Rational{Float64}
ERROR: TypeError: in Rational, in T, expected T<:Integer, got Type{Float64}
Stacktrace:
 [1] top-level scope
   @ REPL[1]:1

julia> Rational{Complex{Int}}
ERROR: TypeError: in Rational, in T, expected T<:Integer, got Type{Complex{Int64}}
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

(I was surprised that Rational{Complex{Int}} isn't allowed).

Edit: It's Complex{Rational{Int64}} that can be used,

julia> typeof(im // 2)
Complex{Rational{Int64}}

@henriquebecker91
Copy link
Contributor

Do you want to take over this @cossio? I offer because you seem better prepared and I am finishing my PhD (so time is short), but if not, I think this is small enough to not cause any problems for me.

@cossio
Copy link
Contributor Author

cossio commented Mar 10, 2022

I don't have time for the PR right now, so feel free to do it.

@vtjnash vtjnash added the domain:rationals The Rational type and values thereof label Feb 22, 2024
@vtjnash
Copy link
Sponsor Member

vtjnash commented Feb 22, 2024

Seems #44550 implemented this

@vtjnash vtjnash closed this as completed Feb 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:rationals The Rational type and values thereof
Projects
None yet
Development

No branches or pull requests

6 participants