Erlang Central

Difference between revisions of "String Is Valid Number"

From ErlangCentral Wiki

(typo)
(Added a new (shorter) function to achieve the results.)
Line 47:Line 47:
 
15> {ok, [Val15], _} = io_lib:fread("~u", "22"), is_integer(Val15).
 
15> {ok, [Val15], _} = io_lib:fread("~u", "22"), is_integer(Val15).
 
true
 
true
 +
</code>
 +
 +
Another simple function to return only true or false could be defined the following way:
 +
 +
<code>
 +
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).
 
</code>
 
</code>
  
 
[[Category:CookBook]][[Category:NumberRecipes]]
 
[[Category:CookBook]][[Category:NumberRecipes]]

Revision as of 05:13, 14 August 2009

Problem

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

Solution

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").
false
2> {ok, [Num], _} = io_lib:fread("~d", "42"), is_number(Num).
true
3> {ok, [Num2], _} = io_lib:fread("~u", "42"), is_number(Num2).
true
4> {ok, [Num3], _} = io_lib:fread("~u", "42"), is_number(Num3).
true
5> {ok, [Num4], _} = io_lib:fread("~u", "42.0"), is_number(Num4).
true
6> {ok, [Num5], _} = io_lib:fread("~f", "42.0"), is_number(Num5).
true
7> io_lib:fread("~u", "2+3i").    
{ok,[2],"+3i"}
8> {ok, [Num6], _} = io_lib:fread("~f", "3.1416"), is_number(Num6). 
true
9> io_lib:fread("~f", "2/3").    
{error,{fread,float}}
10> io_lib:fread("~f", "hello").
{error,{fread,float}}

Discussion

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).
false
14> {ok, [Val14], _} = io_lib:fread("~f", "3.0"), is_float(Val14).
true
15> {ok, [Val15], _} = io_lib:fread("~u", "22"), is_integer(Val15).
true

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).