PHP中的某些浮点值应该总和为零,但不是

时间:2011-06-28 08:51:14

标签: php

  

可能重复:
  Floating point inaccuracy examples

<?php
$a = 128.3;
$b = 140.7;
$c = 12.4;
echo $a-$b+$c;   //2.30926389122E-14
?>

它将显示“2.30926389122E-14”

为什么不是零?

<?php
$a = 112.7;
$b = 125.2;
$c = 12.5;
echo $a-$b+$c;   //0
?>

它们之间有什么区别?

2 个答案:

答案 0 :(得分:11)

不是一个错误,它是IEEE754浮点标准的一个非常有据可查的现象。

表示浮点数的位数有限,让我看看是否可以记住,是的,任意两个不同数字之间的无限实数。

这意味着你不能代表所有实数,但必须提供近似值。

修复的方法是不要假设数字可以准确表示。你应该检测一个数字是否足够接近为零而不是等于零,你可以通过根据你的数字和操作选择一个适当小的误差值来做到这一点。

阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic作为详细论文(警告,这可能有点难以阅读),或The Floating Point Guide有更温和的介绍以及BC Math package的链接PHP(任意精度算术)可能对您有用。

答案 1 :(得分:4)

PHP doc比我更好地回答:

  

浮点数有限   精确。虽然这取决于   系统,PHP通常使用IEEE   754双精度格式,其中   将给出最大相对误差   以1.11e-16的顺序舍入。   非基本算术运算   可能会给出更大的错误   当然,错误编程必须是   考虑几个操作时   配混。

     

另外,理性数字   完全可以表示为浮动   基数10中的点数,如0.1或   0.7,没有精确表示为浮点数   使用的基数为2的数字   在内部,无论大小   尾数。因此,他们不可能   转换成内部二进制文件   对手没有一点损失   精确。这可能会导致混淆   结果:例如,   通常((0.1 + 0.7)* 10)   返回7而不是预期的8,   因为内部代表会   是这样的   7.9999999999999991118 ....

     

所以永远不要相信浮点数结果   到最后一位数,从不比较   相等的浮点数。   如果需要更高的精度,那么   任意精度数学函数和   gmp功能可用。

修改:您的问题标题询问了如何修复。这很简单......四舍五入。 $val = round($val, 2);