Convert Elixir String to Integer or Float

I need to convert a string to a floating point value or an integer. There was no method such as,

string_to_integer

9 Answers

Check and .

4

In addition to the and functions which José suggested you may also check String.to_integer/1 and String.to_float/1.

Hint: See also to_atom/1,to_char_list/1,to_existing_atom/1for other conversions.

Thanks folks on this page, just simplifying an answer here:

{int_val, ""} = Integer.parse(val)

as it validates that the entire string was parsed (not just a prefix).

1

There are 4 functions to create number from string

  • String.to_integer, String.to_float
  • Integer.parse, Float.parse

String.to_integer works nicely but String.to_float is tougher:

iex()> "1 2 3 10 100" |> String.split |> Enum.map(&String.to_integer/1)
[1, 2, 3, 10, 100]

iex()> "1.0 1 3 10 100" |> String.split |> Enum.map(&String.to_float/1)
** (ArgumentError) argument error
    :erlang.binary_to_float("1")
    (elixir) lib/enum.ex:1270: Enum."-map/2-lists^map/1-0-"/2
    (elixir) lib/enum.ex:1270: Enum."-map/2-lists^map/1-0-"/2

As String.to_float can only handle well-formatted float, e.g: 1.0, not 1 (integer). That was documented in String.to_float's doc

Returns a float whose text representation is string.

string must be the string representation of a float including a decimal point. In order to parse a string without decimal point as a float then should be used. Otherwise, an ArgumentError will be raised.

But Float.parse returns a tuple of 2 elements, not the number you want, so put it into pipeline is not "cool":

iex()> "1.0 1 3 10 100" |> String.split \
|> Enum.map(fn n -> {v, _} = Float.parse(n); v end)

[1.0, 1.0, 3.0, 10.0, 100.0]

Using elem to get first element from tuple make it shorter and sweeter:

iex()> "1.0 1 3 10 100" |> String.split \
|> Enum.map(fn n -> Float.parse(n) |> elem(0) end)

[1.0, 1.0, 3.0, 10.0, 100.0]

You can convert it to a char_list and then use the Erlang to_integer/1 or to_float/1.

E.g.

iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}

iex> myInt
23
1

The problem with using is that is will parse any non-numeric part of the string as long as it is in the tail end. For example:

Integer.parse("01") # {1, ""}
Integer.parse("01.2") # {1, ".2"}
Integer.parse("0-1") # {0, "-1"}
Integer.parse("-01") # {-1, ""}
Integer.parse("x-01") # :error
Integer.parse("0-1x") # {0, "-1x"}

Similarly String.to_integer/1 has the following results:

String.to_integer("01") # 1
String.to_integer("01.2") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")
String.to_integer("0-1") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")
String.to_integer("-01") # -1
String.to_integer("x-01") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")
String.to_integer("0-1x") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")

Instead, validate the string first.

re = Regex.compile!("^[+-]?[0-9]*\.?[0-9]*$")
Regex.match?(re, "01") # true
Regex.match?(re, "01.2") # true
Regex.match?(re, "0-1") # false
Regex.match?(re, "-01") # true
Regex.match?(re, "x-01") # false
Regex.match?(re, "0-1x") # false

The regular expression could be simpler (e.g. ^[0-9]*$) depending on your use case.

Decimal.new("1") |> Decimal.to_integer
Decimal.new("1.0") |> Decimal.to_float
1

If you wanted to convert a string to whatever numeric type is within the string & remove all other characters, this is probably overkill, but will return a float if its a float or an int if its an int or nil if the string does not contain an numeric type.

@spec string_to_numeric(binary()) :: float() | number() | nil
def string_to_numeric(val) when is_binary(val), do: _string_to_numeric(Regex.replace(~r{[^\d\.]}, val, ""))
defp _string_to_numeric(val) when is_binary(val), do: _string_to_numeric(Integer.parse(val), val)
defp _string_to_numeric(:error, _val), do: nil
defp _string_to_numeric({num, ""}, _val), do: num
defp _string_to_numeric({num, ".0"}, _val), do: num
defp _string_to_numeric({_num, _str}, val), do: elem(Float.parse(val), 0)

You can use to_integer/1 and to_float/1

String.to_integer(numstr || "0")
String.to_float(numstr || "0.0")
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Marcus Vance

Marcus Vance

Cybersecurity & Digital Privacy Researcher

Marcus Vance is a cybersecurity auditor and technology writer dedicated to educating the public about online safety, data privacy regulations, enterprise security, and emerging cyber threats.

Share this article
Twitter Facebook Pinterest