在PHP中奇怪添加数字字符串

时间:2011-12-07 22:07:04

标签: php floating-point comparison numeric

我将两个数字字符串$ a和$ b加在一起,然后将结果与另一个数字字符串$ c进行比较。所有三个数字都存储为字符串,并在比较步骤中由PHP转换为浮点数。

出于某种原因,测试$ a + $ b == $ c不会评估为真,即使它应该。

您可以使用此脚本重新创建问题:

<?php
$a = "-111.11";
$b = "-22.22";
$c = "-133.33";

echo '$a is '.$a."\n";
echo '$b is '.$b."\n";
echo '$c is '.$c."\n";
echo '$a + $b is '.($a+$b). "\n";

if ($a + $b == $c) {
    echo 'a + b equals c'."\n";
} else {
    echo 'a + b does not equal c'."\n"; 
}
?>

奇怪的是,如果我稍微改变这些值,以便$ a = -111.11,$ b = -22.23和$ c = -133.34,它会按预期工作。

我错过了一些明显的东西,或者这是PHP的错误?

3 个答案:

答案 0 :(得分:5)

在此页面上的大红色框中:http://php.net/manual/en/language.types.float.php

从不比较浮点数是否相等。

基本上,你没有得到正确的数字,因为它们以稍微不同的格式保存,所以当你比较时,它会被搞砸。

@Corbin的链接非常好,所以我只是为了爱而添加它 http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

每个计算机科学家应该知道的关于浮点运算的内容

  

本文提供了一个关于浮点的那些方面的教程   对计算机系统的设计者有直接影响。它始于   关于浮点表示和舍入误差的背景,   继续讨论IEEE浮点标准,以及   最后举例说明了计算机构建者如何能够做得更好   支持浮点。

答案 1 :(得分:2)

您遇到了浮点运算的限制。正如有一些数字你不能完全用十进制表示(例如1/3),所以有些数字你不能完全用浮点二进制表示。

您永远不应该尝试比较浮点数的相等性,因为浮点的限制使得您比较的变量不太可能具有与您认为的值完全匹配的实际值。你需要添加一个“软糖因子”,也就是说,如果这两个数字在某个容差范围内相似,那么你应该认为它们是相等的。

您可以通过从另一个数字中减去一个数字并查看绝对结果是否低于您的阈值(在我的示例中为0.01)来执行此操作:

if (abs ($someFloatingPointNumber - $someOtherFloatingPointNumber) <= 0.01)
{
    // The values are close enough to be considered equal
}

当然,这与可以通过连续数学运算进行的舍入误差相结合意味着浮点数通常不是最佳选择,应该尽可能避免。例如,如果您正在处理货币,请将您的值存储为次要单位的整数(英镑为便士,美元为美分等),并且只能通过除以100转换为主要单位进行显示。

答案 2 :(得分:1)

你的号码总是有两个小数位吗?

如果是这样,你可以试试这个:

$aDec = round($a * 100);
$bDec = round($b * 100);
$cDec = round($c * 100);

if ($aDec + $bDec == $cDec) {
    ...
}