php7的浮点数,php7.1浮点数运算问题

博客内容描述了在PHP环境中遇到的浮点数精度丢失问题,导致接口返回的金额数据在APP中解析错误。问题源于php7.1版本的浮点数序列化精度配置,尽管尝试调整serialize_precision配置但问题依然存在。解决方案是将金额转换为整型(分)进行计算,以避免浮点数运算的精度损失。给出了元转分和分转元的函数示例,并强调对于金融项目,推荐使用整型存储和运算金额以确保精度。
摘要由CSDN通过智能技术生成

最近在项目中遇到一个问题,测试服务器接口返回金额精度缺失,导致app解析不正确发生闪退。调试后发现浮点数在json_encode后损失了精度,如下图所示。

0818b9ca8b590ca3270a3433284dd417.png

网上说是因为php7.1版本的serialize_precision配置不当导致,但是查看配置文件后发现配置正确,默认值为-1。

在服务器上测试浮点数运算如下:

0818b9ca8b590ca3270a3433284dd417.png

测试后发现浮点数的加减运算会导致精度损失。

我们都知道计算机是通过二进制数存储浮点数的一个近似值,浮点数之间的比较和计算难免有误差。

单精度 float 的存储方式如下:

0818b9ca8b590ca3270a3433284dd417.png

双精度 double 的存储方式如下:

0818b9ca8b590ca3270a3433284dd417.png

php7.1版本可以通过设置serialize_precision和precision两个配置项来指定浮点数精度,但是也不能保证满足项目对于浮点数运算的严格要求。

解决方案是将项目中的金额单位从元(浮点数,保留两位小时)转成分(整型)运算,最后除以100避免了浮点数加减运算导致的精度损失。

示例代码如下:

/**

* 元转分

*

* @param $amount

* @return mixed

*/

public static function yuanToFen($amount)

{

return $amount * 100;

}

/**

* 分转元

*

* @param $amount

* @return float

*/

public static function fenToYuan($amount)

{

return $amount / 100;

}

/**

* 元相加运算,不损失精度

*

* @param $yuanAmounts

* @return int

*/

public static function yuanAdd(...$yuanAmounts)

{

$fenAmountTotal = 0;

foreach ($yuanAmounts as $yuanAmount) {

$fenAmountTotal += intval(self::yuanToFen(round($yuanAmount, 2)));

}

return self::fenToYuan($fenAmountTotal);

}

由于本地安装php7.1版本测试未发现相同现象,仔细对比服务器上配置后发现是由于precision配置项被改成-1所致。

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

综上,虽然这个问题主要原因是随意修改配置,且测试服务器php版本比生产环境的7.0版本高,但是生产环境也出现过浮点数精度导致的bug。因此,如果项目对浮点数精度要求严格,尤其是金融项目,建议将浮点数转成整型存储和运算,也有利于数据库存储查询的性能,减少不必要的困扰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值