0

嗨,我有一个定义为的函数

int compareAB(float A, float B)  
{  
    if(A > B) 
    {  
        return 1;  
    }
    else if(A < B)
    {
        return -1;  
    }  
    else
    {
        return 0;
    }
}

从性能工具中可以看出,上述功能在我的项目中比较花费了太多时间。我可以改善它的运行时间吗?

我认为的一种方法是取两个数字的差,然后将其与零进行比较。

谢谢,

编辑:此功能用于维护搜索树数据结构的排序比较功能。现在还更正了返回值。

4

3 回答 3

5

这看起来像是一种试图规避“不应该在浮点上比较相等”规则的人为方式。比较不等式与比较等式并没有太大区别,因为在这两种情况下都隐含地依赖浮点精度。你最后的'else'语句是一个隐含的A == B。

正常的习惯用法是if (::fabs(A - B) < e)e 是一些容忍度,尽管在你的情况下你不需要::fabs.

如果您想要正、负和相等的不同结果(在计算精度的范围内),请执行以下操作

if (A - B > e){
    return 0;
} else if (A - B < -e){
    return 1;
} else {
    return -1;
}

您可以期望的最好的是将 e 设置为std::numeric_limits<double>::epsilon()。实际值取决于为达到 A 和 B 所执行的计算步骤数。1e-08 可能是现实的。

至于速度,不幸的是:我看不出这是瓶颈或运行速度更快。

于 2013-05-28T10:03:46.223 回答
0

这里的问题之一是返回值完全不正确。第一个返回值应该是 1,第二个应该是 -1,第三个应该是 0。如果您使用它进行排序,则排序可能不稳定,这会增加其运行时间。

原则上你可以 return a-b,除非你要处理NaNs。

于 2013-05-28T10:35:49.930 回答
0

浮点比较可能比普通整数比较更昂贵,尤其是在您没有专用浮点硬件的情况下。

幸运的是,在比较浮点数时可以使用整数比较,在某些情况下:

1) 这仅在使用 IEEE754 浮点格式时有效。2) 它不适用于 NaN:s。

访问底层表示是欠精细的行为,因为 C 语言没有指定它使用哪种浮点格式。

无论如何,诀窍在于它仅在浮点数具有相同符号时才有效。而且,在这种情况下,比较两个浮点数的整数表示与比较浮点数本身是相反的。

我没有对下面的代码进行性能测量,但很可能它比您的原始代码更快。如果有的话,请让我知道性能提升!

int compareAB(float a_orig, float b_orig)
{
  /* Get the underlying representation of A and B. */
  long a = *(unsigned long *)&a_orig;
  long b = *(unsigned long *)&b_orig;

  if (a < 0)
  {
    if (b < 0)
    {
      /* Both are negative. The order of the integer representation is
       * the OPPOSITE of the order of the floating-point value. */
      if (a > b)
      {
        return -1;
      }
      else if (a < b)
      {
        return 1;
      }
      else
      {
        return 0;
      }
    }
    else
    {
      /* A is negative, B isn't => A is smaller. */
      return -1;
    }
  }
  else if (b < 0)
  {
    /* B is negative, A isn't => B is smaller. */
    return 1;
  }
  else
  {
    /* Both are positive. */
    if (a > b)
    {
      return 1;
    }
    else if (a < b)
    {
      return -1;
    }
    else
    {
      return 0;
    }
  }
}

您可以使用以下方法进行测试:

#include <stdio.h>

float values[] = {-100.0F,
                  -50.0F,
                  0.0F,
                  50.0F,
                  100.0F };

void test(float a, float b)
{
  const char * p = 0;
  printf("%f is ", a);

  switch (compareAB(a, b))
  {
  case -1: p = "smaller than"; break;
  case  0: p = "equal to"; break;
  case  1: p = "greater than"; break;
  }

  printf("%s %f\n", p, b);
}

int main(void)
{
  int i;

  for (i = 0; i < sizeof(values)/sizeof(values[0]); ++i)
  {
    int j;
    for (j = 0; j < sizeof(values)/sizeof(values[0]); ++j)
    {
      test(values[i], values[j]);
    }
  }
}

它提供与使用原始代码时相同的输出,即:

-100.000000 is equal to -100.000000
-100.000000 is smaller than -50.000000
-100.000000 is smaller than 0.000000
-100.000000 is smaller than 50.000000
-100.000000 is smaller than 100.000000
-50.000000 is greater than -100.000000
-50.000000 is equal to -50.000000
-50.000000 is smaller than 0.000000
-50.000000 is smaller than 50.000000
-50.000000 is smaller than 100.000000
0.000000 is greater than -100.000000
0.000000 is greater than -50.000000
0.000000 is equal to 0.000000
0.000000 is smaller than 50.000000
0.000000 is smaller than 100.000000
50.000000 is greater than -100.000000
50.000000 is greater than -50.000000
50.000000 is greater than 0.000000
50.000000 is equal to 50.000000
50.000000 is smaller than 100.000000
100.000000 is greater than -100.000000
100.000000 is greater than -50.000000
100.000000 is greater than 0.000000
100.000000 is greater than 50.000000
100.000000 is equal to 100.000000
于 2013-05-28T14:10:19.143 回答