为什么这个erlang二进制文件失败了binary_to_term / 1?

时间:2016-07-31 14:22:26

标签: erlang

我将这个二进制文件传递给binary_to_term / 1。据我所知,它是格式良好的,应该通过,但它会导致badarg错误。谁能告诉我为什么?

> B = <<131,104,3,100,0,2,111,107,100,0,7,82,69,65,76,83,88,80,
      108,0,0,0,1,70,127,240,0,0,0,0,7,162,106>>.

> binary_to_term(B).
** exception error: bad argument
     in function  binary_to_term/1
        called as binary_to_term(<<131,104,3,100,0,2,111,107,100,0,7,82,69,65,76,83,88,
                                   80,108,0,0,0,1,70,127,240,0,0,...>>)

根据文档,二进制文件应该像这样分解:

131  %% encoding version number
104 3  %% a tuple with three elements
100 0 2 111 107  %% the atom length 2 'ok'
100 0 7 82 69 65 76 83 88 80  %% the atom length 7 'REALSXP'
108 0 0 0 1  %% a list with one element
70 127 240 0 0 0 0 7 162  %% a float encoded in eight bytes
106  %% end of list

给出类似的东西:

{ok, 'REALSXP', [123.456]}

唯一看起来不完全清楚的是浮动。是八字节序列

<<127,240,0,0,0,0,7,162>>

对于编码为“big-endian IEEE格式的8个字节”的浮点有效吗?

如果不是float部分,那么这个二进制文件还有什么东西会绊倒binary_to_term?

感谢和祝福

伊万

1 个答案:

答案 0 :(得分:4)

这是因为<<127,240,0,0,0,0,7,162>>是64位IEEE float中的NaN值,而Erlang根本不支持创建NaN和Infinity浮点值(参见this)。

1> <<Sign:1, Exponent:11, Fraction:52>> = <<127,240,0,0,0,0,7,162>>.
<<127,240,0,0,0,0,7,162>>
2> Exponent.
2047
3> Fraction.
1954
4> 16#7ff.
2047

来自https://en.wikipedia.org/wiki/Double-precision_floating-point_format#Exponent_encoding

  

指数000 16 和7ff 16 具有特殊含义:

00016 is used to represent a signed zero (if M=0) and subnormals (if M≠0); and 
7ff16 is used to represent ∞ (if M=0) and NaNs (if M≠0),
     

其中M是分数尾数。

如果将这8个字节更改为有效的非NaN / Infinity 64位IEEE浮点数,则一切都按预期工作:

1> binary_to_term(<<131,104,3,100,0,2,111,107,100,0,7,82,69,65,76,83,88,80,108,0,0,0,1,70,0,0,0,0,0,0,0,0,106>>).
{ok,'REALSXP',[0.0]}