奇怪的PHP浮点行为 [英] Weird PHP floating point behavior

查看:194
本文介绍了奇怪的PHP浮点行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个奇怪的问题:

  $ 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
------------------ // --------------------- -

这怎么可能,我在干什么?

解决方案

你没有做错任何事情。漂浮是众所周知的不正确的。从文档(在巨大的红色警告框中):


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

另外,有理数可以精确地表示为浮点在基数为10的点号(如0.1或0.7)中没有精确的表示形式作为基数为2的浮点数,在内部使用,无论尾数的大小。因此,他们不能被转换成他们的内部二进制对应,没有一点精确度的损失。这可能会导致混乱的结果:例如,floor((0.1 + 0.7)* 10)通常会返回7,而不是预期的8,因为内部表示将类似于7.9999999999999991118类似的内容。

所以不要相信浮点数结果到最后一个数字,也不要直接比较浮点数是否相等。如果需要更高的精度,则可以使用任意精度数学函数 gmp 功能可用。


Having weird problem:

$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"]));

And this is output I get:

------------------//--------------------
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 
------------------//----------------------- 

How is this possible, what am I doing wring ?

解决方案

You aren't doing anything wrong. Floats are notoriously innaccurate. From the docs (In the huge red warning box):

Floating point numbers have limited precision. Although it depends on the system, PHP typically uses the IEEE 754 double precision format, which will give a maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic operations may give larger errors, and, of course, error propagation must be considered when several operations are compounded.

Additionally, rational numbers that are exactly representable as floating point numbers in base 10, like 0.1 or 0.7, do not have an exact representation as floating point numbers in base 2, which is used internally, no matter the size of the mantissa. Hence, they cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9999999999999991118....

So never trust floating number results to the last digit, and do not compare floating point numbers directly for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available.

这篇关于奇怪的PHP浮点行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆