PHP简单的数学计算

3

你能帮我看一下这个计算吗?它应该输出"equal",但是却给了我"not equal"

<?php
$tl_pax = 1;
$ct_pax = 2;
$at_pax = 2;

$a = 0.5;
$b = 0.2;
$c = 0.2;
$d = 0.2;
$e = 0.2;
$f = 0.2;
$g = 0.2;
$h = 0.9;

$sum = $a + $b + $c + $d + ($e * $tl_pax) + ($f * $ct_pax) + ($g * $at_pax) + $h;

$total = 3;

if($total == $sum){
    echo 'equal: ' . $sum . ' - ' . $total;
}
else{
    echo 'not equal: ' . $sum . ' - ' . $total;
}
?>

求和和总计的输出是什么? - Madara's Ghost
可能是 浮点数不精确的例子 的重复。 - Gordon
5个回答

5
这是与二进制浮点数相关的舍入误差的常见情况。有些数字在二进制中无法准确表示,因此结果会有一定的偏差。关于此问题的详细信息,请参阅维基百科有关浮点数的文章。
在这种情况下通常的模式是选择一个delta并将其与之进行比较。
 if(abs($total - $sum) < 0.01)
   echo "equal";

你需要根据使用情况恰当地选择Delta应用程序。


2
也许你应该这样写:if(abs($total - $sum) < 0.01) - Medo42

3

失去了说相等的可信度(可能真的不相等)。 - Vadiklk
但它们不一定相等。 - Madara's Ghost
@Rikudo 第二个问题…我正在寻找更好的解决方案。 - genesis
@Bart 这并不完全正确,因为我是第一个提出这个问题的。而且,我检查的数字比其他人更小。你可以自己想一想。 - genesis
@genesis,除非您的浮点算术存在某种错误,否则9+1确切等于10。 - Medo42
显示剩余5条评论

2
由于浮点运算的缘故,你的总和实际上类似于2.9999999999999999999,当你打印它时,PHP会将其隐藏起来。在此处查看floor((0.1+0.7)*10)示例:http://php.net/manual/en/language.types.float.php 比较浮点数相等是不可取的。正确的方法是使用范围进行比较,例如:
if($total-0.0000001 <= $sum && $sum <= $total+0.0000001){

你可以在这里看到它的实际效果:http://codepad.org/kaVXM5g0 那行代码的意思是,$total必须在0.0000001以内才被认为是相等的。你可以根据需要选择数字来确定精度。
或者,在这种情况下,你也可以将$sum四舍五入,但基本上你所做的就是将范围从2.5-3.499...改为2.9999999-3.0000001

1

这种差异是由于浮点精度限制造成的。

像0.9(9/10)这样的值不能被准确地写成二进制浮点数,就像0.3333…(1/3)不能被准确地写成十进制小数一样。这意味着例如$h持有着一个不准确的、四舍五入的0.9的表示。因此,您的计算结果非常接近3,但并不完全等于3。


1

浮点数很麻烦。

来自http://php.net/float的引用

“所以永远不要相信浮点数结果的最后一位数字,也永远不要将浮点数进行相等比较。如果需要更高的精度,可以使用任意精度数学函数和gmp函数。”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接