修复 PHP7.1、7.2beta 中 JSON_encode () 处理 float/double 型数值时溢出的问题
在 PHP7.1、7.2beta 中,使用 json_encode()
函数处理 float/double
型数值时会出现溢出。
对此,我参考网上的方法写了一个 package
,欢迎使用 ^_^ 。
感谢 @ElfSundae 解答,这个问题确实是由于 php.ini
中 serialize_precision
项中配置不当引起的,是我理解错了。
PHP 官方 WIKI 在此:https://wiki.php.net/rfc/precise_float_val...
示例
>>> $a = 0.1 + 0.7
=> 0.8
>>> printf('%.20f', $a)
=> 0.79999999999999993339
>>> json_encode($a)
=> "0.7999999999999999"
>>> \YaJson::encode($a)
=> "0.8"
用法
-
修复精度并进行
json_encode
:$data = [ 'a' => 0.1 + 0.7, 'b' => ['string1', 'string2'], ]; \YaJson::encode($data);
-
只获取修复后的数据,不进行
json_encode
:$data = [ 'a' => 0.1 + 0.7, 'b' => ['string1', 'string2'], ]; \YaJson::prepare($data);
安装
-
安装包文件
composer require "seekerliu/laravel-another-json:dev-master"
配置
Laravel 5.5
Laravel 5.5
安装新包后会默认执行@php artisan package:discover
命令,所以可以不进行下面的操作。
-
注册
ServiceProvider
及Facade
:php artisan package:discover
-
如需修改默认循环深度、精度位数,则创建配置文件:
php artisan vendor:publish
Laravel 5.4 及以下
-
注册
ServiceProvider
及Facade
:'providers' => [ //... Seekerliu\YaJson\ServiceProvider::class, ], 'aliases' => [ //... 'YaJson' => Seekerliu\YaJson\Facade::class, ],
-
如需修改默认循环深度、精度位数,则创建配置文件:
php artisan vendor:publish --provider="Seekerliu\YaJson\ServiceProvider"
Github: https://github.com/seekerliu/laravel-anoth...
感谢博主提供的思路: http://www.itread01.com/articles/148977474...
本作品采用《CC 协议》,转载必须注明作者和本文链接
准确的说是 7.1 才出问题
第一个contribute
@mingyun 谢谢~ 我又测试了一下,确实只有 7.1 和 7.2 有这个问题,已修改正文描述~ :thumbsup:
@Rekkles :thumbsup::thumbsup::thumbsup:
把 serialize_precision 修改成别的值就好了啊, 最好在代码里改
ini_set('serialize_precision', 14);
把你的演示修改了下: https://3v4l.org/T1ZmY
JSON 目的是为数据交换,各个语言或系统中的「对象」表示不一样,JSON 就是中间桥梁。
把你的 json_encode 后看起来错误的数据放到别的系统上执行 json_decode 如果得到的值是期望的就行。
https://wiki.php.net/rfc/precise_float_val...
@ElfSundae 谢谢~原来官方说明在这里,找了很久都没找到 ^_^。
刚刚测试了一下,如果不把 json_encode 看起来错误的数据处理一下,放在别的系统是有可能得到错误的结果的。
如果别的系统配置的精度设置很高,就会得到
0.7999999999999
这样的结果,而不是0.8
。例如: https://3v4l.org/0IoWn而精度设置稍低,又正常了 https://3v4l.org/gJqSE
@ElfSundae 其实我的例子,最好的解决方法是用
bcmath
哈哈嗯 浮点精度在每个系统的处理有差异, PHP 使用的是 IEEE 754 ,PHP 7.1 的 json_encode 使用了 serialize_precision (默认 -1) 是把浮点精度提高了。要跟 7.1 之前的结果一样的话最便捷的就是修改 serialize_precision 为 precision 值,14 是默认值。但是最好的方法是永远不要相信浮点的精度,这在很多系统上都有说明,比如 PHP 的警告:http://php.net/manual/zh/language.types.fl...
@ElfSundae 说来这个问题也不算 bug 了。。原本指望 7.2 能改回去 :smirk:
我还是回去补习下浮点数在内存的表示。。
厉害,大佬
个人认为 Json只是一种数据传输格式 并不应该参与运算处理之类的逻辑
浮点数运算 应该手动处理 比如bcmath函数或者类型转换 可能稍微繁琐点 但不会出现由Json编码导致的错误异常
Json错误异常(json_last_error())目前已经有10种(PHP7.3为止)
所以应该养成一种习惯 先做好数据处理工作 再Json编码 这样由Json编码导致的异常可尽量避免