我有一个允许用户通过PayPal购买产品的网站,我允许使用折扣码。我是这样添加折扣的:
'cost' => -number_format($discount, 2)
然而,有时PayPal会抛出一个错误,当我试图检查。
调试时,我发现有时cost
的值会类似于-8.066666666667
。我最初感到困惑,但发现在参数列表中移动反运算符(在第一个参数之前)解决了这个问题。
我想确保我明白发生了什么,这样我就不会再犯同样的错误。我想应该是这样的:
-
number_format($discount, 2)
显然返回一个字符串(我认为它返回float) - 将负运算符放在number_format() '前面将导致返回的字符串结果自动转换为浮点数,这将产生舍入误差
- 从字符串转换为浮点数后,返回相反的(反)结果
- 返回结果没有四舍五入到小数点后两位
我对发生的事情的理解正确吗?
应该是…
'cost' => '-' . number_format($discount, 2)
…或者只是…
'cost' => number_format(-$discount, 2)
…如果你想获得一个字符串作为相应的值(你可能会这样做)。
使用当前的代码,您首先获得字符串(number_format
调用的结果),然后使用一元减号操作符将其转换回数字。而这个数字和之前一样,也遇到了浮点数不准确的问题。
我相信你把number_format函数搞错了。该函数将float
转换为string
,使其易于阅读。根据手册,该函数还在任意三位数组之间添加逗号以使结果数字更易于阅读,并在需要时添加尾随点,后跟十进制数字。
这会使您的代码混乱,这实际上是对字符串取反。一般来说,对字符串取反是没有意义的:)
您想要的是一个将浮点数舍入为给定小数位数的函数。这是通过round
函数实现的:
round(19.0398, 2); // returns 19.04
关于你的理解,大部分是正确的,但是你忽略了一个重要的微妙的情况。
就像我说的,number_format返回一个字符串,现在如果你对一个字符串取反,这个字符串会自动转换成一个数字。如何将字符串转换为数字?字符串的开头部分(由数字组成)将被转换为数字,但从第一个字符开始的所有非数字字符将被忽略。
因此,将字符串"12a33"转换为数字将得到数字12,而字符串"17,500"将转换为数字17。
你现在看到问题了吗?如果你的折扣变量包含一个较大的数字,比如10000
,那么number_format(10000, 2)
将产生字符串"10,000"
,而否定这个字符串将产生数字-10
。
我不知道$discount
是否会那么大,但你应该考虑使用round
而不是number_format
。
这将使它工作,
'cost' => number_format(-1*$discount, 2)