PHP: Ceil function rounding issue
在我的WordPress主题函数中,这段代码被用来计算总计费金额:ceil(($cost * (1 + ($charges / 100))) * 100);。
下面的场景发生了一些计算错误。
脚本:
1 2 3 4
| $charges = 9;
$cost = 100;
echo ceil(($cost * (1 + ($charges / 100))) * 100); |
上面的代码输出10901,而应该是10900。
它适用于其他场景,如:
1 2 3 4 5
| $charges = 4;
$cost = 90.7;
echo ceil(($cost * (1 + ($charges / 100))) * 100);
//outputs 9433, which is fine because manual calculation results 9432.8 |
号
问题:
为什么会这样?
我该怎么预防呢?
有没有其他函数可以四舍五入到下一个最接近的整数?(仅当金额为浮动值时)
- @菲尔,这些答案都没有帮助,首先,这不是一个数学问题。第二,它几乎可以正常工作,但只会对以00结尾的特定数字产生错误。请取消标记问题或共享有用的资源。谢谢
- 似乎你真的面临着数字精度带来的问题。尽管我发现简化你的方程确实有帮助:ceil($cost*(100+$charge));,请参见:rexteter.com/qqeyos31143。
- 谢谢@cars10m,还有一个问题。您的公式在rexteter.com上运行良好,但在我的服务器上,它有相同的问题。:(我跑5.6.32
- @它无疑是一个浮点运算问题。例如,100 * (1 + (9 / 100))以109.00000000000001的形式出现。这就是为什么ceil()看起来是四舍五入的原因。请阅读我在你问题顶部链接的两篇文章
- @菲尔,现在有点道理了,那么我如何用普通的浮点方法计算精确的值呢?
- 在使用ceil()函数之前,您可以尝试使用round($cost*(100+$charge),6)四舍五入到小数点后6位的最接近数字。然而,据报道,在某些情况下,round()是一辆小车。否则,您也可以通过创建一个圆形字符串来绕行,如sprintf('%0.6f',$cost*(100+$charge)),然后继续使用它进行数学运算(它将隐式转换回float)。在这两种情况下,随后将应用ceil()函数将值转换为"下一个更大的整数"。
- @cars100谢谢你的帮助,圆函数做的工作。虽然,ceil()函数做得很好,但它在一个场景中出错(数字以00结尾),所以我决定使用round函数。
问题是您正在将CEIL应用于外部表达式。尝试将其重写为:
1 2 3 4
| $charges = 9;
$cost = 100;
echo ($cost + ceil($cost * $charges / 100)) * 100; |
这将按预期输出10900。
更新
正如@cars10m所建议的,简化表达式有助于:
1
| echo ceil($cost * 100 + $cost * $charges); |
号
更新2
您还可以使用BCMath库进行精确的数学运算:
- 谢谢@olim saidov,但对于其他情况来说,这不太好。尝试使用这些值$charges = 4; $cost = 90.7;,结果是9470,而应该是9433。
- 你能解释一下计算逻辑吗?为什么应该是9433?
- 1)charges/100=0.042)0.04 + 1 = 1.043)1.04*cost=94.3284)94.328 * 100 = 9432.85)四舍五入到下一个整数将使其成为9433。
- 新的解决方案在我的服务器上不起作用。我在运行5.6.32。
- 使用@cars10m方法,rexteter给出了正确的结果,但在我的服务器上,它给出的结果与我以前的表达式相同。可能是因为PHP版本等原因,不过,bcscale似乎可以工作。我会做不同的测试,很快回来。谢谢你的帮助!:)
- 谢谢你为我提供帮助。顺便说一句,我必须使用round函数来解决我的问题,正如@cars10m建议的那样。