利用PHP高精确度运算BC函数库解决小数计算异常问
不管哪种第三方方式都有可能出现掉单的情况,出现掉单的原因可能有很多种。但有一种非常常见,就是在异步通知的时候订单校验失败(不管哪种支付方式订单校验是必须要做的一种安全校验,当然实际还需校验其他的东西,比如说appid);而之所以出现,金额校验不通过情况就是因为某些金额数字包含某些小数;如果是直接比较,那么显然会出问题。
现在举一个例子,假设使用的微信支付,支付金额为32.30;那么订单的实际支付金额是32.30,微信异步通知的金额是3230(以分为单位),如果直接比较,那么就返回false,那自然接下来更新订单状态等等一系列操作都不能执行下去了,因为校验都没通过。
var_dump(32.30*100==3230);——-显示bool(false)
按理说,我们人的数学计算,这个结果应该是true,然而机器和人还是不一样的,要知道现在的机器是基于二进制的,因此才会造成误差,具体大家可以在网上阅读相关资料。
然而如果这么来比较,又会显示不一样的结果:
var_dump(bcmul(32.30,100)==3230);—-显示bool(true)
而其中的bcmul就属于PHP数学扩展中的BC函数库,是其中用于对2个任意精度数字乘法计算的函数。
BC函数库包含了加减乘除、乘方、二次根等多种高精度计算函数,具体如下:
- bcadd — 2个任意精度数字的加法计算
- bccomp — 比较两个任意精度的数字
- bcdiv — 2个任意精度的数字除法计算
- bcmod — 对一个任意精度数字取模
- bcmul — 2个任意精度数字乘法计算
- bcpow — 任意精度数字的乘方
- bcpowmod — 求高精度数字乘方求模,数论里非常常用
- bcscale — 设置所有bc数学函数的默认小数点保留位数
- bcsqrt — 任意精度数字的二次方根
- bcsub — 2个任意精度数字的减法
以上函数具体内容可以参考PHP官方文档关于BC函数库的介绍:
http://php.net/manual/zh/ref.bc.php