让我们看一下rfc4627
生成的 JSON:
> io:format("~s~n", [rfc4627:encode({obj, [{"age", 45.99}]})]).
{"age":4.59900000000000019895e+01}
事实证明,rfc4627
通过调用 对浮点值进行编码float_to_list/1
,它使用具有 20 位精度的“科学”表示法。 正如 Per Hedeland 在 2007 年 11 月的 erlang-questions 邮件列表中指出的那样,这是一个奇怪的选择:
一个合理的问题可能是为什么 float_to_list/1 在内部使用的 64 位浮点数(又名 C 双精度)只能容纳 15-16 个数字时生成 20 位数字 - 我不知道副手是什么一个 128 位的浮点数会有,但可能远远超过 20,所以也不是这样。我猜想早在黑暗时代,有人认为 20 是一个不错的偶数(我希望不是我:-)。6.30000 形式当然只是 ~p/~w 格式。
然而,事实证明这实际上不是问题!事实上,45.990000000000002
等于45.99
,所以你确实在前端得到了正确的值:
> 45.990000000000002 =:= 45.99.
true
如上所述,64 位浮点数可以容纳 15 或 16 位有效数字,但45.990000000000002
包含 17 位数字(数一数!)。看起来您的前端尝试以比实际包含的精度更高的精度打印数字,从而使数字看起来不同,即使它实际上是相同的数字。
问题的答案是浮点数学坏了吗?考虑到计算机如何处理浮点值,更详细地了解为什么这实际上是有意义的。