PHP7.1 json_encode() 浮动问题

新手上路,请多包涵

这不是一个问题,因为它更像是一个注意事项。我将使用 json_encode() 的应用程序更新为 PHP7.1.1,我看到一个问题,即浮点数被更改为有时会扩展 17 位数字。根据文档,PHP 7.1.x 在编码双精度值时开始使用 serialize_precision 而不是精度。我猜这导致了一个示例值

472.185

成为

472.18500000000006

在该值经过 json_encode() 之后。自从我发现以来,我已经恢复到 PHP 7.0.16,我不再遇到 json_encode() 的问题。在恢复到 PHP 7.0.16 之前,我还尝试更新到 PHP 7.1.2。

这个问题背后的原因确实源于 PHP - Floating Number Precision ,但是最终的所有原因都是因为 json_encode() 中从 precision 到 serialize_precision 用法的变化。

如果有人确实知道这个问题的解决方案,我会非常乐意聆听推理/修复。

多维数组摘录(之前):

 [staticYaxisInfo] => Array
                    (
                        [17] => stdClass Object
                            (
                                [variable_id] => 17
                                [static] => 1
                                [min] => 0
                                [max] => 472.185
                                [locked_static] => 1
                            )

                    )

在经历了 json_encode() 之后……

 "staticYaxisInfo":
            {
                "17":
                {
                    "variable_id": "17",
                    "static": "1",
                    "min": 0,
                    "max": 472.18500000000006,
                    "locked_static": "1"
                }
            },

原文由 Gwi7d31 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 415
2 个回答

这让我有点抓狂,直到我终于找到 了这个错误,它将你指向 这个 RFC ,它说

目前 json_encode() 使用设置为14的EG(精度)。这意味着最多14位数字用于显示(打印)数字。 IEEE 754 double 支持更高的精度和 serialize() / var_export() 使用 PG(serialize_precision) 默认设置为 17 以更精确。由于 json_encode() 使用 EG(精度), json_encode() 删除小数部分的较低数字并破坏原始值,即使 PHP 的浮点数可以保持更精确的浮点值。

并且(强调我的)

此 RFC 提议引入一个新设置 EG(precision)=-1 和 PG(serialize_precision)=-1,它使用 zend_dtoa() 的模式 0,它使用更好的算法来舍入浮点数(-1 用于指示 0 模式) .

简而言之,有一种使 PHP 7.1 json_encode 使用新的和改进的精度引擎的新方法。在 php.ini 中,您需要将 serialize_precision 更改为

serialize_precision = -1

您可以验证它是否适用于此命令行

php -r '$price = ["price" => round("45.99", 2)]; echo json_encode($price);'

你应该得到

{"price":45.99}

原文由 Machavity 发布,翻译遵循 CC BY-SA 3.0 许可协议

作为插件开发人员,我没有对服务器的 php.ini 设置的一般访问权限。因此,根据 Machavity 的回答,我编写了这段可以在 PHP 脚本中使用的小代码。只需将它放在脚本之上,json_encode 就会照常工作。

 if (version_compare(phpversion(), '7.1', '>=')) {
    ini_set( 'serialize_precision', -1 );
}

在某些情况下,有必要再设置一个变量。我将其添加为第二个解决方案,因为我不确定第二个解决方案是否在第一个解决方案已被证明有效的所有情况下都能正常工作。

 if (version_compare(phpversion(), '7.1', '>=')) {
    ini_set( 'precision', 17 );
    ini_set( 'serialize_precision', -1 );
}

原文由 alev 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏