How to convert a binary string to an integer or a float?

11,415

Solution 1

No quick way to do it. Use something like this instead:

bin_to_num(Bin) ->
    N = binary_to_list(Bin),
    case string:to_float(N) of
        {error,no_float} -> list_to_integer(N);
        {F,_Rest} -> F
    end.

This should convert the binary to a list (string), then try to fit it in a float. When that can't be done, we return an integer. Otherwise, we keep the float and return that.

Solution 2

This is the pattern that we use:

binary_to_number(B) ->
    list_to_number(binary_to_list(B)).

list_to_number(L) ->
    try list_to_float(L)
    catch
        error:badarg ->
            list_to_integer(L)
    end.

Solution 3

Intermediate conversion to list is unnecessary since Erlang/OTP R16B:

-spec binary_to_number(binary()) -> float() | integer().
binary_to_number(B) ->
    try binary_to_float(B)
    catch
        error:badarg -> binary_to_integer(B)
    end.
Share:
11,415

Related videos on Youtube

BAR
Author by

BAR

No expertise, just good arguments.

Updated on December 08, 2020

Comments

  • BAR
    BAR over 3 years

    I have binary strings in the form of either:

    <<"5.7778345">>
    

    or

    <<"444555">>
    

    I do not know before hand whether it will be a float or integer.

    I tried doing a check to see if it is an integer. This does not work since it is binary. I alos tried converting binary to list, then check if int or float. I did not have much success with that.

    It needs to be a function such as:

    binToNumber(Bin) ->
      %% Find if int or float
      Return.
    

    Anyone have a good idea of how to do this?

  • I GIVE TERRIBLE ADVICE
    I GIVE TERRIBLE ADVICE over 13 years
    Not in this case. Converting with binary_to_term and term_to_binary will at best change the binary string to a regular list/string. No float or integer will be obtained. See my reply for a way to do it.
  • nmichaels
    nmichaels over 13 years
    @I GIVE TERRIBLE ADVICE: I was suggesting using term_to_binary to get the binary in the first place. Then converting back is trivial. Of course, it could still be completely unrealistic if the OP doesn't have control over where the data comes from.
  • I GIVE TERRIBLE ADVICE
    I GIVE TERRIBLE ADVICE over 13 years
    That makes sense, in that context.
  • YOUR ARGUMENT IS VALID
    YOUR ARGUMENT IS VALID over 13 years
    You probably want list_to_float not string:to_float.
  • I GIVE TERRIBLE ADVICE
    I GIVE TERRIBLE ADVICE over 13 years
    It would also be a valid approach yes. Probably faster. string:to_float will tolerate more garbage, which might or might not be an advantage. I upvoted your answer.
  • YOUR ARGUMENT IS VALID
    YOUR ARGUMENT IS VALID over 13 years
    I mostly suggested it because <<"123.456seven">> would be considered valid but not <<"123456seven">>. An intentionally garbage tolerant version would be able to handle the integer case too.

Related