感谢 @地狱星星:
原因已找到, 该现象只出现在PHP 7.1+版本上
建议使用默认值 serialize_precision = -1 即可 
参考: https://wiki.php.net/rfc/prec... 
----------------------------------------------------------------------------------

事情是这样的,项目里发现一个奇怪的现象,json_encode一个带浮点价格的数据, 出现溢出, 比如:

  1. <?php

  2. echo json_encode(277.2);

  3. // 输出结果为: 277.199999999999989

这明显是不能接受的, 数据虽然很接近, 但毕竟已经变更了
下意识地认为这是php的一个bug, 不能准确地json序列化一个浮点小数
这个问题google了半天竟然也无果, 然后我跟同事说, 你们json_encode数据里有小数的时候, 记得先number_format()转化成字符串.

自己又写了个fix方法, 遍历数据, 把is_float()的数据都用number_format()转化了

  1. function json_encode_pre($d, $depth=128, $level=0){

  2. if($level>$depth) return $d;

  3. if(is_array($d)){

  4. foreach ($d as $i => $v) { $d[$i] = json_encode_pre($v, $depth, $level+1); }

  5. return $d;

  6. }

  7. if(is_float($d)){

  8. # 测试发现number_format有效数字低于18(保守取16)时,不会溢出

  9. $p = 16 - strlen(intval($d));

  10. $f = number_format($d, $p);

  11. if($p>1){ $f = preg_replace('/0+$/','', $d); }

  12. return $d;

  13. }

  14. return $d;

  15. }

  16. echo number_format(277.2, 14); // 当18位有效数字处理(277.2已有4位有效数字)

  17. // 277.199999999999989

  18. echo number_format(277.2, 12); // 当16位

  19. // 277.2000000000000

  20. echo json_encode(json_encode_pre(277.2));

  21. // "277.2"

看到这结果时, 便猜测是有效数字位数的问题导致了溢出, PHP怎么会有这么蠢的设计呢?这是我当时的想法.

然后想着是不是能从源码下手, 于是查了下php源码, 发现这段代码:

  1. static inline void php_json_encode_double(smart_str *buf, double d, int options) /* {{{ */

  2. {

  3. size_t len;

  4. char num[PHP_DOUBLE_MAX_LENGTH];

  5. php_gcvt(d, (int)PG(serialize_precision), '.', 'e', num);

  6. len = strlen(num);

  7. if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < PHP_DOUBLE_MAX_LENGTH - 2) {

  8. num[len++] = '.';

  9. num[len++] = '0';

  10. num[len] = '\0';

  11. }

  12. smart_str_appendl(buf, num, len);

  13. }

是的, 竟然发现了配置项serialize_precision, 这个配置我当初的理解是serialize()方法用的, 而我当初尝试修改过配置项precision, 然并卵, 原来json_encode会用到serialize_precision, 于是修改php.ini, 把它设为16, 原来是17还是18忘了.

  1. <?php

  2. echo json_encode(277.2);

  3. // 输出结果为: 277.2

如果你想重现我的问题, 很简单, 把serialize_precision设为20或更大, 至于这个有效数字最大值是多少才不会溢出, 我还不知道跟什么有关系, 希望能有大神指点了.
我是通过改配置数值, 出现溢出的值再减去2来用的.

附上配置项说明, 从官方说明上看, 很难想像是跟json_encode是有关系的.

  1. ; php.ini

  2. ; When floats & doubles are serialized store serialize_precision significant

  3. ; digits after the floating point. The default value ensures that when floats

  4. ; are decoded with unserialize, the data will remain the same.

  5. serialize_precision = 16

  6. ; The number of significant digits displayed in floating point numbers.

  7. ; http://php.net/precision

  8. precision = 16

另外源码里有个json_encode的选项JSON_PRESERVE_ZERO_FRACTION, 这个的意思是如果是个是个整数, 是否保留小数点和0, 来看测试结果:

  1. <?php

  2. echo json_encode(277.0);

  3. // 277

  4. echo json_encode(277.0, JSON_PRESERVE_ZERO_FRACTION);

  5. // 277.0

来源:https://blog.csdn.net/moliyiran/article/details/81179825

PHP7 serialize_precision 配置不当导致 json_encode() 浮点小数溢出错误相关推荐

  1. 记一次CentOS7因Redis配置不当导致被Root提权沦为矿机修复过程

    未曾想过,那些年影视剧中黑客们的精彩桥段,竟在2020这个充满魔幻的年份,变成了现实. 前几日傍晚突然收到了来自阿里云安全中心的提醒,服务器疑似受到攻击了.想不到我那用作学习的机器,有朝一日竟然沦为矿 ...

  2. IPTABLES规则配置不当导致的路径MTU无法更新

    问题主机Linux系统的iptables配置如下,旨在仅开放http和https的80和443端口,拒绝所有其他的连接.第三条规则允许状态为建立的数据包进入本机,即本机主动发起的连接,允许回复报文进入 ...

  3. 配置不当导致无法加载odoo-10.0模块

    启动odoo-bin时出错 2017-01-05 06:38:51,046 5480 INFO ? odoo: Odoo version 10.0 2017-01-05 06:38:51,046 54 ...

  4. Springboot之actuator配置不当漏洞(autoconfig、configprops、beans、dump、env、health、info、mappings、metrics、trace)

    前言 Actuator 是 springboot 提供的用来对应用系统进行自省和监控的功能模块,借助于 Actuator 开发者可以很方便地对应用系统某些监控指标进行查看.统计等.在 Actuator ...

  5. 微软低代码工具 Power Apps 配置不当,暴露3800万条数据记录

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 Upguard 研究院称,由于微软 Power Apps 默认配置安全性薄弱,敏感数据如 COVID-19 打疫苗情况.社保号码和邮件地址遭泄露 ...

  6. CSA:《云安全风险、合规性和配置不当报告》公开发布!

    (微信搜索"国际云安全联盟",回复关键词"云安全"下载本报告) 如何推进好云安全管理成为很多组织面临的问题,CSA受VMware委托完成<云安全风险.合规 ...

  7. Redis配置不当可导致服务器被控制,已有多个网站受到影响 #通用程序安全预警#...

    文章出自:http://news.wooyun.org/6e6c384f2f613661377257644b346c6f75446f4c77413d3d 符合预警中"Redis服务配置不当& ...

  8. 技术分享|由于Nginx配置不当而导致内网资产暴漏

    前言 当前有部分企业通常会在外网部署一些Nginx服务器,然后在Nginx中配置域名绑定.用户访问对应的域名,Nginx通过反向代理将对应的内网资源反馈给互联网上的用户,这样企业可以把服务器部署在自己 ...

  9. java redis使用卡死_记一次找因 redis 使用不当导致应用卡死 bug 的过程

    原标题:记一次找因 redis 使用不当导致应用卡死 bug 的过程 作者:小木 my.oschina.net/xiaomu0082/blog/2990388 首先说下问题现象:内网sandbox环境 ...

最新文章

  1. 计算机科学与技术第6次上机实验报告,计算机科学与技术第次实验报告-20210602214116.docx-原创力文档...
  2. Projects(子查询、连接,分组,聚合)
  3. python数字图像处理(17):边缘与轮廓
  4. 获取某一日期为当年的第几旬
  5. REVERSE-COMPETITION-GeekChallenge2021
  6. 利用Teensy进行EM410x卡模拟以及暴力破解EM410X类门禁系统可行性猜想
  7. 区块链开发公司:区块链技术如何改变个人数据安全
  8. init是一个自定义方法名
  9. PHP学习笔记之PDO
  10. flink sink jdbc没有数据_一套 SQL 搞定数据仓库?Flink 有了新尝试
  11. 再别极域(亲测有效)
  12. 渗透工具-masscan
  13. 常用的字符编码:ASCII、Unicode、UTF-8
  14. 树莓派 | RSSHub+TTRSS
  15. 工控安全入门常用逻辑编程
  16. windows-xp桌面图标有蓝底怎么去掉:电脑桌面图标有蓝色阴影的解决办法
  17. django bootstrap3
  18. 明日之后服务器崩了最新消息,《明日之后》崩了是什么原因?明日之后崩了怎么登陆服务器...
  19. 快手小店通涨粉推广怎么做?
  20. 国际物流专线是什么意思?

热门文章

  1. python爬取考研成绩什么时候出来_用Python爬取了考研吧1000条帖子,原来他们都在讨论这些!...
  2. 1.18.5.流式概念、动态表(Dynamic Table)、DataStream上的关系查询、动态表 连续查询(Continuous Query)、在流上定义表、处理时间
  3. jenkins的安装配置,插件配置,安装插件,配置maven,jdk路径,配置安装插件,项目配置,自动构建配置
  4. Java连接HBASE数据库,创建一个表,删除一张表,修改表,输出插入,修改,数据删除,数据获取,显示表信息,过滤查询,分页查询,地理hash
  5. 项目管理过程组(5)与知识领域(10)
  6. Java将网络地址对应的图片转成本地的图片
  7. Hibernate模糊查询
  8. 配置DispatcherServlet
  9. 斯坦福python中文分词stanza
  10. oracle中的open,Oracle 深入分析Open过程