嗨我有一个定义为
的函数int compareAB(float A, float B)
{
if(A > B)
{
return 1;
}
else if(A < B)
{
return -1;
}
else
{
return 0;
}
}
以上功能在我的项目中进行比较需要花费太多时间,我可以从性能工具中看到。我可以改善它的运行时间。
我认为的一种方法是将2个数字相差,然后将其与零进行比较。
谢谢,
编辑:此功能用于排序比较功能,用于维护搜索树数据结构。现在也更正了返回值。
答案 0 :(得分:4)
这看起来像是试图规避“永远不应该比较浮点上的相等”规则的一种人为的方式。比较不等式与比较相等性并没有太大的不同,因为在两种情况下都依赖于浮点精度。你的最后'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可能是现实的。
至于速度,不幸的是它:我看不出这是瓶颈或跑得更快。
答案 1 :(得分:0)
这里的一个问题是返回值完全不正确。第一个返回值应为1,第二个应为-1,第三个应为零。如果您使用它进行排序,排序可能不稳定,这会增加其运行时间。
原则上,您只需返回a-b
,除非您打算处理NaN
。
答案 2 :(得分:-1)
浮点比较可能比普通整数比较昂贵,特别是如果没有专用的浮点硬件。
幸运的是,在比较浮点数时,您可以使用整数比较,在某些情况下:
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