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)
6 Likes

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.

3 Likes

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?

2 Likes

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?