繁体   English   中英

Erlang Cowboy回复json数据,浮点数精度错误?

[英]Erlang cowboy reply json data , float number precision is wrong?

代码在这里:

RstJson = rfc4627:encode({obj, [{"age", 45.99}]}),
{ok, Req3} = cowboy_req:reply(200, [{<<"Content-Type">>, <<"application/json;charset=UTF-8">>}], RstJson, Req2)

然后我从前端客户那里得到了错误的数据:

{
  "age": 45.990000000000002
}

浮点数精度已更改! 我该如何解决这个问题?

让我们看一下rfc4627生成的JSON:

> io:format("~s~n", [rfc4627:encode({obj, [{"age", 45.99}]})]).
{"age":4.59900000000000019895e+01}

事实证明, rfc4627通过调用float_to_list/1 rfc4627编码浮点值,该方法使用精度为20位的“科学”表示法。 正如Per Hedeland在2007年11月的erlang-questions邮件列表中指出的那样 ,这是一个奇怪的选择:

一个合理的问题可能是为什么当内部使用的64位浮点数(又名C双精度数)只能容纳15-16个浮点数时,为什么float_to_list / 1生成20位数字-我不知道该用什么一个128位浮点数将具有,但大概超过20个,因此也不是。 我想可以追溯到黑暗时代,有人认为20是个不错的甚至是个数字(我希望不是我:-)。 6.30000格式当然只是〜p /〜w格式。


但是,事实证明这实际上不是问题! 实际上, 45.990000000000002等于45.99 ,因此您在前端确实获得了正确的值:

> 45.990000000000002 =:= 45.99.
true

如上所述,一个64位浮点数可以容纳15或16个有效数字,但是45.990000000000002包含17个数字(计数!)。 看起来您的前端试图打印比实际包含的精度更高的数字,从而使数字看起来不同,即使实际上是相同的数字也是如此。


问题的答案浮点数学运算是否已损坏? 考虑到计算机如何处理浮点值,我们将详细介绍为什么这实际上有意义。

rfc4627中的编码浮点数函数为:

encode_number(Num, Acc) when is_float(Num) ->
  lists:reverse(float_to_list(Num), Acc).

我这样改变了它:

encode_number(Num, Acc) when is_float(Num) ->
  lists:reverse(io_lib:format("~p",[Num]), Acc).

问题解决了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM