Erlang Central

String Is Valid Number

Revision as of 05:13, 14 August 2009 by Nrobidoux (Talk | contribs)


You need to check if a given string contains a valid number.


We suppose that we want to check the text strings: "42", "2+3i", "3.1416", "2/3", "hello". Erlang is trickier than Scheme, since it does not provide the native support for fractional values or imaginary numbers. However, the general algorithm we need to use is something like the following: 1 Try to convert the string to a number (of some kind). 2 Pass the resulting value to the built-in Erlang predicates is_number.

Let's see some examples:

1> is_number("42").
2> {ok, [Num], _} = io_lib:fread("~d", "42"), is_number(Num).
3> {ok, [Num2], _} = io_lib:fread("~u", "42"), is_number(Num2).
4> {ok, [Num3], _} = io_lib:fread("~u", "42"), is_number(Num3).
5> {ok, [Num4], _} = io_lib:fread("~u", "42.0"), is_number(Num4).
6> {ok, [Num5], _} = io_lib:fread("~f", "42.0"), is_number(Num5).
7> io_lib:fread("~u", "2+3i").    
8> {ok, [Num6], _} = io_lib:fread("~f", "3.1416"), is_number(Num6). 
9> io_lib:fread("~f", "2/3").    
10> io_lib:fread("~f", "hello").


Clearly, Erlang's generic io_lib:fread functionality does not provide everything we want. It doesn't handle fractional values with the easy and grace of Scheme, and it does not understand imaginary numbers. However, this functionality could be provided in a library that provides an "is_number" interface similar to what we want.

We could also follow the Perl approach of using regular expressions to determine if the string is a number, but that is a topic for another Recipe.

There may also be times when you want to tell if a given number is an integer number a floating-point number. One solution is using the io_lib:fread function as before, and then using one of the Erlang built-in predicates is_integer and is_float. procedures:

13> {ok, [Val13], _} = io_lib:fread("~f", "3.0"), is_integer(Val13).
14> {ok, [Val14], _} = io_lib:fread("~f", "3.0"), is_float(Val14).
15> {ok, [Val15], _} = io_lib:fread("~u", "22"), is_integer(Val15).

Another simple function to return only true or false could be defined the following way:

is_numeric(L) when is_list(L) ->
    Float = (catch erlang:list_to_float(L)),
    Int = (catch erlang:list_to_integer(L)),
    is_number(Float) orelse is_number(Int).