[erlang-bugs] binary pattern matching fails with 32-bit float, if decimal representation of the number cannot be converted to binary exactly

Ulf Wiger ulf.wiger@REDACTED
Mon Aug 1 12:06:59 CEST 2011


Compiling to BEAM ASM illustrates why:

>> case <<1.1:32/float>> of <<1.1:32/float>> -> ok end.
> ** exception error: no case clause matching <<63,140,204,205>>


{function, f, 0, 2}.
  {label,1}.
    {func_info,{atom,bin_match},{atom,f},0}.
  {label,2}.
    {move,{literal,<<63,140,204,205>>},{x,0}}.
    {test,bs_start_match2,{f,3},1,[{x,0},0],{x,1}}.
    {test,bs_get_float2,
          {f,3},
          2,
          [{x,1},
           {integer,32},
           1,
           {field_flags,[{anno,[6,{file,"./bin_match.erl"}]},unsigned,big]}],
          {x,2}}.
    {test,is_eq_exact,{f,3},[{x,2},{float,1.1}]}.
    {test,bs_test_tail2,{f,3},[{x,1},0]}.
    {move,{atom,ok},{x,0}}.
    return.
  {label,3}.
    {case_end,{x,0}}.

The constructor pattern is evaluated at compile-time, so the binary appears in the ASM.
The match pattern uses the bit syntax operators to extract a float, and then checks the result (now using native float representation) to the hard-coded float 1.1.

Whether or not this is desirable is another discussion, but you can work around it by constructing the binaries and comparing them. It's not that the construction itself is non-deterministic.

BR,
Ulf W


On 1 Aug 2011, at 11:53, Вадзім Зенька wrote:

> WHAT:
> binary pattern matching fails with 32-bit float, if decimal
> representation of the number cannot be converted to binary exactly
> 
> EXAMPLE:
> following code fails:
> 
> % "1.1" does not have exact binary representation
>> case <<1.1:32/float>> of <<1.1:32/float>> -> ok end.
> ** exception error: no case clause matching <<63,140,204,205>>
> 
>> case <<63,140,204,205>> of <<1.1:32/float>> -> ok end.
> ** exception error: no case clause matching <<63,140,204,205>>
> 
> although
> 
>> case <<1.1:32/float>> of <<63,140,204,205>> -> ok end.
> ok
> 
> % "1.5" has exact binary representation
>> case <<1.5:32/float>> of <<1.5:32/float>> -> ok end.
> ok
> 
> % 64-bit floats work well
>> case <<1.1:64/float>> of <<1.1:64/float>> -> ok end.
> ok
> 
> --
> З павагай, Вадзім Зенька
> v@REDACTED
> vadzim@REDACTED
> +375.29.407.27.17
> _______________________________________________
> erlang-bugs mailing list
> erlang-bugs@REDACTED
> http://erlang.org/mailman/listinfo/erlang-bugs

Ulf Wiger, CTO, Erlang Solutions, Ltd.
http://erlang-solutions.com






More information about the erlang-bugs mailing list