奇怪的PHP浮点行为

时间:2012-09-05 23:16:42

标签: php floating-point

有奇怪的问题:

$testTotal = 0;
foreach($completeBankArray as $bank){
   var_dump($testTotal);
   echo  " + ";
   var_dump(floatval($bank["amount"]));
   echo " = ".(floatval($testTotal) + floatval($bank["amount"]))."</br>";
   $testTotal = floatval(floatval($testTotal) + floatval($bank["amount"]));

这是我得到的输出:

------------------//--------------------
float(282486.09) + float(15) = 282501.09
float(282501.09) + float(3.49) = 282504.58
float(282504.58) + float(22.98) = 282527.55999999
float(282527.55999999) + float(5.2) = 282532.76
float(282532.76) + float(39.98) = 282572.73999999
float(282572.73999999) + float(2.6) = 282575.33999999
float(282575.33999999) + float(2.99) = 282578.32999999 
------------------//----------------------- 

这怎么可能,我在做什么呢?

4 个答案:

答案 0 :(得分:7)

你没有做错任何事。漂浮物众所周知是无用的。从docs(在巨大的红色警告框中):

  

浮点数的精度有限。虽然它取决于系统,但PHP通常使用IEEE 754双精度格式,由于舍入的顺序为1.11e-16,因此会产生最大的相对误差。非基本算术运算可能会产生更大的误差,当然,当复合多个运算时,必须考虑误差传播。

     

此外,基本10中的浮点数精确表示的有理数,如0.1或0.7,没有精确表示为基数2中的浮点数,无论尾数的大小如何,它都在内部使用。因此,它们不能在没有很小精度损失的情况下转换为它们的内部二进制对应物。这可能会导致令人困惑的结果:例如,floor((0.1 + 0.7)* 10)通常会返回7而不是预期的8,因为内部表示将类似于7.9999999999999991118 ....

     

所以永远不要将浮点数结果信任到最后一位数,并且不要直接比较浮点数是否相等。如果需要更高的精度,arbitrary precision math functionsgmp函数可用。

答案 1 :(得分:1)

浮动从来都不是精确的,从长远来看会有很大差异。如果您正在使用精确数学,请阅读bc library

答案 2 :(得分:0)

经典数字精度示例。计算机以二进制形式存储浮点数。

简短的回答是计算机无法准确表示二进制中的某些浮点数。

长答案涉及在数字基础之间移动。如果你有一个浮点数,你就不能完全用二进制表示它,除非分母包含的数据可以分解为2的幂。

答案 3 :(得分:0)

其他答案让我们深入了解了为什么你会用浮动来获得这种行为。

如果你正在处理钱,你问题的一个解决方案是使用整数而不是浮点数,并处理美分而不是美元。然后,您需要做的就是格式化输出以包含小数。