Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binary to Integer -> Erlang

I have a binary M such that 34= will always be present and the rest may vary between any number of digits but will always be an integer.

M = [<<"34=21">>]

When I run this command I get an answer like

hd([X || <<"34=", X/binary >> <- M])

Answer -> <<"21">>

How can I get this to be an integer with the most care taken to make it as efficient as possible?

like image 666
BAR Avatar asked Jan 23 '11 01:01

BAR


3 Answers

[<<"34=",X/binary>>] = M,
list_to_integer(binary_to_list(X)).

That yields the integer 21

like image 133
Aliud Alius Avatar answered Nov 19 '22 20:11

Aliud Alius


As of R16B, the BIF binary_to_integer/1 can be used:

OTP-10300

Added four new bifs, erlang:binary_to_integer/1,2, erlang:integer_to_binary/1, erlang:binary_to_float/1 and erlang:float_to_binary/1,2. These bifs work similarly to how their list counterparts work, except they operate on binaries. In most cases converting from and to binaries is faster than converting from and to lists.

These bifs are auto-imported into erlang source files and can therefore be used without the erlang prefix.

So that would look like:

[<<"34=",X/binary>>] = M,
binary_to_integer(X).
like image 21
legoscia Avatar answered Nov 19 '22 22:11

legoscia


A string representation of a number can be converted by N-48. For multi-digit numbers you can fold over the binary, multiplying by the power of the position of the digit:

-spec to_int(binary()) -> integer().
to_int(Bin) when is_binary(Bin) ->
    to_int(Bin, {size(Bin), 0}).

to_int(_, {0, Acc}) ->
    erlang:trunc(Acc);
to_int(<<N/integer, Tail/binary>>, {Pos, Acc}) when N >= 48, N =< 57 ->
    to_int(Tail, {Pos-1, Acc + ((N-48) * math:pow(10, Pos-1))}).

The performance of this is around 100 times slower than using the list_to_integer(binary_to_list(X)) option.

like image 2
lafka Avatar answered Nov 19 '22 20:11

lafka