比较双精度的奇怪行为,两个PHP双精度值不相等

问题描述 投票:5回答:4

我在PHP中有两个看似相等的double值(至少在回显它们时)。

但是当将它们与double equals进行比较时,出于某种原因,它的评估结果为false。进行这种比较时是否有任何特殊注意事项?

php compare double
4个回答
9
投票

您不应该使用==运算符比较浮点数。

看到大警告和explanation in the php manual

可行的是断言两个数字在彼此之间的某个小距离内如下:

if(abs($a - $b) < 0.0001) {
    print("a is mostly equal to b");
}

原因是由于在将小数转换为二进制之后执行的浮点运算导致的舍入误差,然后转换回十进制。这些来回转换导致0.1 + 0.2不等于0.3的现象。


1
投票

float和double永远不应该被比较为相等:有精确错误会使两个数字不同,即使它们看起来相等(当它们被打印出来时,它们通常是圆形的)。

比较的正确方法是使用一些DELTA常量:

define(DELTA, 0.00001); // Or whatever precision you require

if (abs($a-$b) < DELTA) {
  // ...
}

另请注意,这不是PHP特定的,但在其他语言中也很重要(Java,C,...)


1
投票

PHP(as well as in C and many other languages)中浮点数的表示是不精确的。由于这个事实,看似相同的数字实际上可能是不同的,并且比较将失败。相反,选择一些小数字并检查差异是否小于,例如:

if(abs($a-$b)<0.00001) {
  echo "Equal!";
}

另见explanations in the PHP manual


1
投票

我做的一个小功能,希望帮助某人:

function are_doubles_equal($double_1, $double_2, $decimal_count) {
    if (!$decimal_count || $decimal_count < 0) {
        return intval($double_1) == intval($double_2);
    }
    else {
        $num_1 = (string) number_format($double_1, $decimal_count);
        $num_2 = (string) number_format($double_2, $decimal_count);
        return $num_1 == $num_2;
    }
}

用法:

$a = 2.2;
$b = 0.3 + 1.9002;

are_doubles_equal($a, $b, 1); // true : 2.2 == 2.2 
are_doubles_equal($a, $b, 1); // false : 2.2000 == 2.2002
© www.soinside.com 2019 - 2024. All rights reserved.