简单乘法的PHP舍入错误
当使用简单乘法的PHP舍入错误,php,casting,int,rounding,Php,Casting,Int,Rounding,当使用(int)强制转换变量时,PHP似乎舍入错误。为什么? $multiplier = 100000000; $value = 0.01020637; echo (int)($value*$multiplier); 输出:1020636。(意外输出) 输出:1020637。(预期正确输出) 编辑:情况变得更糟 $multiplier = 100000000; $value = 0.01020637; echo $temp = ($value*$multiplier); echo '<b
(int)
强制转换变量时,PHP似乎舍入错误。为什么?
$multiplier = 100000000;
$value = 0.01020637;
echo (int)($value*$multiplier);
输出:1020636
。(意外输出)
输出:1020637
。(预期正确输出)
编辑:情况变得更糟
$multiplier = 100000000;
$value = 0.01020637;
echo $temp = ($value*$multiplier);
echo '<br/>';
echo (int)$temp;
$multiplier=100000000;
$value=0.01020637;
echo$temp=($value*$multiplier);
回声“
”;
回声(内部)$温度;
输出:
1020637
1020636
在处理浮点运算时,事情可能会变得棘手,浮点数学(以及涉及的问题)很容易理解,但在您不期望它们出现时,事情可能会突然出现。就像这里发生的那样。在处理浮点运算时,您可以广泛阅读或使用语言提供的工具
当您关心所涉及的精度时,您应该使用该函数。它是一个“可选”扩展,但如果您关心精度,那么它很快就会被要求
例如:
multiplier = 100000000;
$value = 0.01020637;
echo (int)($value*$multiplier);
echo "\n";
echo bcmul($value, $multiplier, 0);
示例:要在PHP中对浮点进行取整,应使用round()函数。仅强制转换为整数不会正确舍入值 第一个参数是要四舍五入的浮点数(本例中的计算结果),第二个参数是可选的,并指定要返回的小数量(也称为精度)。还有第三个参数,控制模式。它们可以是PHP_ROUND_HALF_UP、PHP_ROUND_HALF_DOWN、PHP_ROUND_HALF_偶数或PHP_ROUND_HALF_奇数 示例来自:
下面是代码()的示例:
PHP(特别是在32位版本中)存在浮点数问题。这就是为什么将float
强制转换为int
会产生不可预测的结果。有关更多详细信息,请参见第页。基本上,你在数学上得到了微小的不精确性,当你尝试做类似于ceil()的事情时,这可能会导致严重的问题
如果您真的需要将数字转换为int
,我建议您先将数字四舍五入
$multiplier = 100000000;
$value = 0.01020637;
$temp = round($value*$multiplier);
echo $temp . '<br/>' . (int)$temp;
$multiplier=100000000;
$value=0.01020637;
$temp=四舍五入($value*$multiplier);
echo$temp.”
。(内部)$temp;
这是通过截断小的浮点错误来实现的。虽然也可以进行截断,但它不是PHP核心的一部分,也不是一个好的整体解决方案。最好的办法是自己编写一个舍入例程,以返回所需的精度。在我工作的项目中,我们就是这么做的。我们编写了自己的舍入函数,它解决了您将遇到的问题。如果不知道你想做什么,很难说这是否是你所需要的,但这是我们在没有bcmath的情况下所做的。你看到的问题如下:
将这样的两个数字相乘时:
$mulitply = 0.1 * 100;
你不是用0.1乘以100,而是用0.09999998。。。
当涉及到(int)
时,它会将像4.999
这样的数字转换为4
,因此当使用(int)
计数时,您的结果1020636.99999999
将变成1020636
$test = (int) bcmul('100000000', '0.01020637');
echo $test
返回正确答案 如果您尝试(int)($value*$multiplier+0.5)会怎么样;“切勿将未知分数强制转换为整数,因为这有时会导致意外结果。
”摘自PHP integer手册。这可能是原因吗?什么是“未知分数”?在我的程序中,($value*multiplier)
表达式将始终解析为整数。将其切换为read($value*$multiplier)(int)
会有帮助吗?或者干脆$temp=($value*$multiplier)$intVal=(int)$temp)
可能会导致预期的结果吗?@bvpx老实说,我不知道。但是我确实发现这个链接,描述了一个与您类似的问题,请查看:应该注意的是,bcmath不是PHP核心函数的一部分,也不是所有服务器都安装了它。没有bcmath,有什么方法可以做到这一点吗?目前我的服务器没有安装它。也许我可以找到一个只包含bcmul函数的库,并将其包含在我的项目中?我怀疑您是否能在这里找到一个很棒的userland解决方案。我可能会礼貌地缠着你的系统管理员安装扩展。在精度至关重要的情况下,我该如何解决这个问题?@bvpx我建议BC数学函数
(,在你的情况下,你需要专门查找bcmul()
函数)或gmp\u mul()
()@bvpx我注意到您询问了一个不需要在PHP中安装其他内容的解决方案。我从一开始就不知道PHP中包含任何类似的函数,我很震惊。@bvpx同样,如果不需要在服务器端执行此计算,我强烈建议使用纯JavaScript。简单地使用:var multiply=var_1*var_2
不会自动给出一个四舍五入的答案,它会给你一个完整的10位小数。该应用程序是一个小型PHP程序,分发到许多计算机上,只运行服务器端,因此我需要将其设置为“裸体”尽可能确保它运行的服务器没有安装bcmath的问题,但也能够正确存储这些值。我有一种直觉,即使用round()
将导致比它解决的问题更多的问题…我希望我可以告诉您不同的情况,但除了将其舍入,没有其他方法可以获得一个干净的数字。bcmath是一个硬截断,以确保您不会遇到那些奇怪的精度问题。你知道你需要多少精度吗?我有点不确定如何回答“我需要多少精度”,但我正在使用的数字将在10000000到0.00000001之间,所有这些数字都需要乘以100000000并正确存储到数据库中。如果必须在服务器上安装bcmath,我不想使用它,但数据库中不能存储不正确的值,这一点非常重要。基本问题是您的号码存储在内存中,类似于1020636.9999992734834
。
$multiplier = 100000000;
$value = 0.01020637;
$temp = round($value*$multiplier);
echo $temp . '<br/>' . (int)$temp;
$mulitply = 0.1 * 100;
$test = (int) bcmul('100000000', '0.01020637');
echo $test