某种情况下1不等于1(PHP)

6

我有一个关联数组,其中的值是浮点数,这些浮点数应该表示概率。因此,我将它们加起来,并要求结果确实为1。

$total = array_sum($array);
echo '$total = '.$total."\n";
if ($total == 1) {
    die("total is 1");
} else {
    die("total is not 1");
}

这段代码神秘地输出:
$total = 1
total is not 1

执行var_dump($total)可以得到float(1),然而$total == (float)1的结果却是false。出了什么问题?


2
https://dev59.com/p2445IYBdhLWcg3w0dZD - thumbmunkeys
可能是浮点数运算有问题吗?的重复问题。 - miken32
@miken32 不完全正确。那个问题是关于一般浮点算术问题的。这个问题是关于 PHP 的 var_dump 函数意外执行舍入(而不是转储变量)。 - Mala
3个回答

4

浮点数的特性是不精确的,由于存储和四舍五入误差等原因,它们很少相等。你应该通过比较两个浮点数是否“足够接近”来进行比较。也就是说,将两个值之间的差的绝对值与一个显著小的误差范围(通常称为“epsilon”)进行比较。

以下是一种实现方法:

if (abs($total - 1) < 0.000000001)
    die("total is 1");
} else {
    die("total is not 1");
}

请注意,只有您的应用程序需要真正确定什么是安全误差范围,并在何时对数字进行舍入以显示。
例如,如果您处理货币值并需要完全精度,更好的解决方案是完全放弃浮点算术。在这种情况下,一个选项是使用整数类型,并将数字存储为美分,在最后一刻才进行除法以向用户显示数字(或甚至不除法,而是将小数点插入字符串中)。

2

在PHP(以及其他语言)中,浮点数不是精确的,因此(float)1实际上可能是1.00000000000000123113.99999999999999823477

有关更多信息,请参见答案PHP-浮点数精度


有没有一种方法可以让 PHP 告诉我它的实际值是什么? - Mala
print(number_format($myNumber, 32); 这段代码可以让你以一定的精度查看它的值,但据我所知,你无法看到确切的值。 - Jordan
whargbl "0.99999999999999988897769753748435" - 我不知道var_dump会这样四舍五入 - Mala

1
将 int 转换执行
if ((int)$total == 1)

而且它会工作:)

编辑: 或者更好的是

$total = (int)array_sum($array);

1
这将不幸对我尝试做的事情没有帮助(请参阅问题顶部)。如果我的值出了问题 - 这段代码要检查的内容 - 而总和实际上是1.3,那么它将通过测试。 - Mala

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