27

我有一个字符串,可以像这样转换为双精度:

double d = [string doubleValue];

的文档doubleValue告诉我们,在溢出时,此方法返回HUGE_VALor -HUGE_VAL。这就是我之前检查的方式:

if (d == HUGE_VAL || d == -HUGE_VAL)
   //overflow

现在,由于添加了新的“-Weverything”警告标志,编译器现在抱怨

Comparing floating point with == or != is unsafe

我该如何解决这个问题?我应该如何进行这些比较?


关于比较两个“正常”浮点数(即不是“HUGE_VAL”),我也有同样的问题。例如,

double a, b;
//...
if (a != b) //this will now yield the same warning
  //...

这应该如何解决?

4

5 回答 5

44

您无需担心此警告。在很多情况下,包括您的情况,这都是无稽之谈。

的文档doubleValue并没有说它返回的东西足够接近HUGE_VAL-HUGE_VAL溢出。它说它会在溢出的情况下准确地返回这些值。

换句话说,在溢出的情况下方法返回的值==HUGE_VALor比较-HUGE_VAL

为什么警告首先存在?

考虑这个例子0.3 + 0.4 == 0.7。此示例的计算结果为 false。人们,包括您遇到的警告的作者,都认为浮点==是不准确的,而意想不到的结果来自这种不准确。

他们都错了。

浮点加法是“不准确的”,从某种意义上说是不准确的:它为您请求的操作返回最接近的可表示浮点数。在上面的示例中,转换(从十进制到浮点)和浮点加法是导致奇怪行为的原因。

另一方面,浮点相等的工作方式与其他离散类型的工作方式几乎完全相同。浮点相等是精确的:除了少数例外(NaN 值和 +0. 和 -0. 的情况),当且仅当所考虑的两个浮点数具有相同的表示时,相等才计算为真。

您不需要 epsilon 来测试两个浮点值是否相等。而且,正如Dewar 所说的那样,示例中的警告0.3 + 0.4 == 0.7应该是 on +,而不是 on ==,这样警告才有意义。

最后,与 epsilon 内的比较意味着不相等的值看起来相等,这不适用于所有算法。

于 2012-07-10T21:30:18.573 回答
12

在这种情况下,请尝试使用>=and <=

于 2012-07-10T22:23:26.990 回答
7

如果你确定你的比较并且你想让它发出叮当声,在你的代码周围加上:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
/* My code triggering the warnings */
#pragma clang diagnostic pop
于 2016-08-22T13:39:41.190 回答
1

对于这个非常简单的用例可能不需要,但这里有一个示例,说明如果您尝试检查数字是否等于 -1,您将如何解释潜在的差异:

#include <float.h>
#include <math.h>

int main(void) {
  float sales = -1;

  // basically if sales == -1
  if (fabs(1 + sales) < FLT_EPSILON) {
    return 0;
  }
}
于 2019-11-01T14:31:48.083 回答
-1

由于浮点类型不准确,浮点数不应与 == 或 != 进行比较,这可能会在使用这些运算符时导致意外错误。您应该测试浮动是否位于彼此的距离内(大多数情况下称为“Epsilon”)。

它可能看起来像这样:

const float EPSILON = 1.0f; // use a really small number instead of this

bool closeEnough( float f1, float f2)
{
    return fabs(f1-f2)<EPSILON; 
    // test if the floats are so close together that they can be considered equal
}
于 2012-07-10T21:04:10.517 回答