Parse 97 or 97.0 to Integer: clever method?

I’m parsing string data from a file written by LabVIEW – numbers written out as strings, which I am parsing to numeric types.

In this example, integers.

The LabVIEW program is a little inconsistent. The pressure settings are always a whole value, but sometimes the LabVIEW program will write out “20” and other times “20.0”

Julia’s built-in parse() will barf on the second one. For example:

input_press = "20"
setpress = parse(Int,input_press)  
println("setpress = ",setpress)

input_press = "20.0"
setpress = parse(Int,input_press)  
println("setpress = ",setpress)

Results in the output:

setpress = 20

ERROR: ArgumentError: invalid base 10 digit '.' in "20.0"
Stacktrace:

Solution

I can use the Parsers package and it’s tryparse() function, which will return nothing if the conversion fails.

using Parsers
input_press = "20"
setpress = Parsers.tryparse(Int,input_press)  
if isnothing(setpress)
    floatpress = Parsers.tryparse(Float64,input_press)
    setpress = Integer(floatpress)
end

println("setpress = ",setpress)

input_press = "20.0"
setpress = Parsers.tryparse(Int,input_press)  
if isnothing(setpress)
    floatpress = Parsers.tryparse(Float64,input_press)
    setpress = Integer(floatpress)
end
println("setpress = ",setpress)

This works. I could even write it into a small function.

However

This being Julia, is there a more clever way to accomplish this?

You could do this, which nicely throws an error if its not actually an integer:

julia> Int(parse(Float64, "23.0"))
23

julia> Int(parse(Float64, "23"))
23

julia> Int(parse(Float64, "23.1"))
ERROR: InexactError: Int64(23.1)

Keep in mind that this method will only be exact for integers up to 2^{53}. Above that, not every Int64 can be represented as Float64 anymore.

I don’t think OP needs to worry about exceeding a pressure of 2^53 (in any unit system I’m aware of). Maybe if they’re modeling the Big Bang in Labview?

If you are sure that you can discard the digits after the decimal point (because they are always zeros), you can use split() before parse():

julia> s = "20.0"; parse(Int, split(s, ".")[1])
20

julia> s = "20"; parse(Int, split(s, ".")[1])
20

round(Int64, parse(Float64, s))

That will silently discard any non-integer part, which doesn’t sound like the desired behavior here:

Depends on what lies in “are always”. If it’s truly always a whole value it changes nothing.

Of course it depends a lot on the application: is an error better than rounding if a user tries to be funny?