Reputation: 2924
I want to read the user input and store it as a Rational, whatever the type: integer, float ot rational. For instance:
5 --> store it as 5//1
2.3 --> store it as 23//10
4//7 --> store it as 4//7
At the moment I wrote the following:
a = convert(Rational,parse(Float64,readline(STDIN)))
which is fine if I input an integer, like 5.
But if I input 2.3, a
stores 2589569785738035//1125899906842624
.
And if I input a fraction (whether in the form 4/7
or the form 4//7
) I get an ArgumentError: invalid number format for Float64
.
How to solve the Float&Rational problems?
Upvotes: 4
Views: 1055
Reputation: 2290
One way is to parse the raw input to an Expr
(symbols), eval the expression, convert it to a Float64
and use rationalize to simplify the rational generated:
julia> rationalize(convert(Float64, eval(parse("5"))))
5//1
julia> rationalize(convert(Float64, eval(parse("2.3"))))
23//10
julia> rationalize(convert(Float64, eval(parse("4/7"))))
4//7
julia> rationalize(convert(Float64, eval(parse("4//7"))))
4//7
rationalize
works with approximate floating point number and you could specify the error in the parameter tol
.
tested with Julia Version 0.4.3
Update: The parse
method was deprecated in Julia version >= 1.0. There are two methods that should be used: Base.parse
(just for numbers, and it requires a Type argument) and Meta.parse
(for expressions):
julia> rationalize(convert(Float64, eval(parse(Int64, "5"))))
5//1
julia> rationalize(convert(Float64, eval(parse(Float64, "2.3"))))
23//10
Upvotes: 8
Reputation: 20774
You could implement your own parse
:
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(Rational{Int}, x)
Upvotes: 0
Reputation: 66
Multiplication (then division) by a highly composite integer works pretty well.
julia> N = 2*2 * 3*3 * 5*5 * 7 * 11 * 13 900900 julia> a = round(Int, N * parse(Float64, "2.3")) // N 23//10 julia> a = round(Int, N * parse(Float64, "5")) // N 5//1 julia> a = round(Int, N * parse(Float64, "9.1111111111")) // N 82//9
Upvotes: 0