[erlang-questions] binary_to_float: <<"2e-1">> versus <<"2.0e-1">>

Per Hedeland per@REDACTED
Sat Jan 31 14:59:44 CET 2015


Peter Morgan <peter.james.morgan@REDACTED> wrote:
>
>Ah, OK - good to know. I'm using the following as a result:
>
>
>btof(<<Coefficient:8, "e-", Remainder/binary>>) when Coefficient >= $0
>andalso Coefficient =< $9 ->
>    binary_to_float(<<Coefficient:8, ".0e-", Remainder/binary>>);
>btof(Float) ->
>    binary_to_float(Float).

If you really don't know anything about the format of the numbers you
receive, that seems like a very limited solution. E.g. I suspect that
you want to handle also at least some of 

<<"2e1">>,<<"-2e-1">>,<<"+2e-1">>,<<"22e-1">>,<<"2">>,<<".2">>,<<"2.">>

- all of which will result in badarg from binary_to_float/1 with the
above code. Since I happened to have to deal with this "strictness"
recently, I cobbled up the below. I believe it should handle all
"reasonable" (and some not so reasonable) formats that a float can be
"given" in - and (intentionally) crash for anything else. Takes an
iodata() argument, since re(3) does.

--Per Hedeland

to_float(Val) ->
    RE = "^\\s*([+-])?(\\d+)?(\\.)?(\\d+)?([Ee][+-]?\\d+)?\\s*$",
    {match, [Sign, Int, Point, Fract, Exp]} =
        re:run(Val, RE, [{capture, [1, 2, 3, 4, 5], list}]),
    list_to_float(Sign ++ float_str(Int, Point, Fract) ++ Exp).

%% make list_to_float/1 happy
float_str(Int, "", "") ->
    Int ++ ".0";
float_str("", _, [_|_] = Fract) ->
    "0." ++ Fract;
float_str([_|_] = Int, _, "") ->
    Int ++ ".0";
float_str([_|_] = Int, _, [_|_] = Fract) ->
    Int ++ "." ++ Fract.



More information about the erlang-questions mailing list