2016-07-31 70 views
2

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

> 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字节”的浮点有效吗?

如果不是浮动部分,那么这个二进制文件还有什么值得注意的是binary_to_term?

与感谢和良好祝愿

伊万

回答

4

这是因为<<127,240,0,0,0,0,7,162>>是64位IEEE浮点NaN值和Erlang不支持在所有建立楠无限的浮点值(见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 具有特殊含义:

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的/无限远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]} 
+0

辉煌的答案!非常感谢!二进制来自C端口,NaN完美匹配。我会在C端抓住它并改变发送的内容。 –