“-Weverything”产生“比较浮动点与==或!=是不安全的”

时间:2012-07-10 20:52:37

标签: objective-c cocoa llvm clang

我有一个字符串,我将其转换为像这样的双字符:

double d = [string doubleValue];

doubleValue的文档告诉我们,在溢出时,此方法会返回HUGE_VAL-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
  //...

如何解决这个问题?

5 个答案:

答案 0 :(得分:35)

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

doubleValue的文档并未说明它在溢出时返回的内容足够接近HUGE_VAL-HUGE_VAL。它表示在溢出的情况下它会返回这些值。

换句话说,方法在溢出时返回的值会将==HUGE_VAL-HUGE_VAL进行比较。

为什么警告首先存在?

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

他们都错了。

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

另一方面,

浮点相等的工作方式与其他离散类型完全相同。浮点相等是精确的:除了小的异常(NaN值和+0。和-0。的情况)之外,当且仅当所考虑的两个浮点数具有相同的表示时,等式才计算为真。 / p>

您不需要epsilon来测试两个浮点值是否相等。而且,正如Dewar says in substance一样,示例0.3 + 0.4 == 0.7中的警告应位于+上,而不是==上,以使警告有意义。

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

答案 1 :(得分:10)

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

答案 2 :(得分:5)

如果您确定自己的比较,并希望告诉它铿锵声,请用以下代码包围您的代码:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
/* My code triggering the warnings */
#pragma clang diagnostic pop

答案 3 :(得分:0)

浮点数不应与==或!=进行比较,因为浮点类型不准确,这可能会在使用这些运算符时导致意外错误。 您应该测试浮子是否位于彼此的距离内(大部分时间称为“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
}

答案 4 :(得分:0)

对于这个非常简单的用例来说,可能不是必需的,但是这里有一个示例,说明了在尝试检查数字是否等于-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;
  }
}