浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为
1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递。
此外,以十进制能够精确表示的有理数如 0.1 或
0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10)
通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似
7.9999999999999991118...。
所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数。
0.3、0.7这样的小数在机器内要换算为二进制,换算成为的二进制有可能是个无限的循环小数,这样就会有误差,不能精确表示。
0.3的二进制格式是:
0.010011001100110011001100110011001100110011001100110011
0.7的二进制格式是:
0.1011001100110011001100110011001100110011001100110011
可以看出位数都是很长的,如果超过机器的精度,就会四舍五入。另外1-0.3、1-0.7的计算过程中也会出现相应的误差,所以浮点数的相等判断没有实际意义,一般是判断两个数的差的绝对值比一个规定的精度小,就算相等。例如:
if (abs(x-y)<0.0000001) echo '相等';