否定number_format()结果会改变有效数字的位数?

时间:2015-09-15 11:30:36

标签: php math floating-point

我有一个网站,允许用户通过PayPal购买产品,我允许折扣代码。我正在添加这样的折扣:

'cost'   => -number_format($discount, 2)

但是,有时PayPal会在我尝试退房时抛出错误。

调试时,我发现cost的值有时会像-8.066666666667一样。我最初感到困惑,但发现在参数列表中移动否定运算符(在第一个参数之前)修复了问题。

我想确保我理解发生了什么,所以我不会再犯同样的错误。我认为这样下去了:

  • number_format($discount, 2)显然返回一个字符串(我认为它返回了浮动状态)
  • 将否定运算符放在number_format()`前面会导致返回的字符串结果自动转换为浮点数,这将导致舍入错误
  • 从字符串转换为浮点后,返回相反(否定)的结果
  • 返回的结果未四舍五入到小数点后两位

我对发生的事情的理解是否正确?

3 个答案:

答案 0 :(得分:2)

应该是......

'cost'   => '-' . number_format($discount, 2)

......或者只是......

'cost'   => number_format(-$discount, 2)

...如果你想获得一个字符串作为相应的值(你可能会这样做)。

使用代码,你首先得到字符串(number_format调用的结果)只返回到带有一元减号运算符的数字。而这个数字与之前的wall of floating point inaccuracies相同。

答案 1 :(得分:1)

我相信你的number_format函数错了。 此功能使float变为string,使其阅读愉快。根据手册,此函数还在任意三个数字组之间添加逗号,以使得结果数字更容易阅读,并且如果需要,后跟点后跟小数位数。

这会弄乱你的代码,实际上是在否定字符串。否定一个字符串一般没有意义:)

你想要的是一个将浮点数舍入到给定小数位数的函数。这是通过round函数:

实现的
round(19.0398, 2); // returns 19.04

关于你的理解,它大多是正确的,但你错过了一个重要的微妙案例。

正如我所说,number_format返回一个字符串,现在如果你否定一个字符串,字符串会自动转换为数字。如何将字符串转换为数字?字符串的初始部分(由数字组成)将转换为数字,但从第一个不是数字开始的所有字符都将被忽略。

因此,将字符串“12a33”变为数字将导致数字12,而字符串“17,500”将变为数字17。

你现在能看到问题吗?如果您的折扣变量包含大数字,请说10000number_format(10000, 2)将生成字符串"10,000",否定此字符串将导致数字-10

我不知道$discount是否会那么大,但你应该考虑使用round而不是number_format来达到目的。

答案 2 :(得分:0)

这将使其有效,

'cost' => number_format(-1*$discount, 2)