高效的浮点比较
efficient floating point comparison
嗨,我有一个函数定义为
int compareAB(float A, float B)
{
if(A > B)
{
return 1;
}
else if(A < B)
{
return -1;
}
else
{
return 0;
}
}
上面的函数在我的项目中花费了太多的时间来比较,因为我可以从性能工具中看到。我能改进它的运行时间吗?
我认为一种方法是取两个数的差,然后与0比较。
谢谢,
编辑:这个函数被用于排序比较函数,用于维护一个搜索树数据结构。现在也更正了返回值。
这看起来像是一种试图规避"不应该对浮点进行相等性比较"规则的人为方式。比较不等号和比较等号没有太大的不同,因为在这两种情况下,你都隐含地依赖于浮点精度。最后的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而执行的计算步骤的数量。
至于速度,很不幸的是:我看不出这是瓶颈或者运行得更快。
这里的一个问题是返回值完全不正确。第一个返回值应该是1,第二个应该是-1,第三个应该是0。如果您使用此方法进行排序,则排序可能不稳定,这会增加其运行时间。
原则上您可以只返回a-b
,除非您要处理NaN
s。
浮点比较可能比普通整数比较更昂贵,特别是在没有专用浮点硬件的情况下。
幸运的是,在某些情况下,您可以在比较浮点数时使用整数比较:
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 %fn", 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
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- C++中高效的大型稀疏块压缩线性方程
- 为什么比较运算符如此快速
- 我可以使用 g++ 进行三种比较 (<=>) 吗?
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 比较字符数组
- 将模板化的类型与C++中的某些类/类型进行比较
- C++自定义比较函数
- 如何比较自定义类的std::变体
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- std::设置自定义比较器
- 布尔比较运算符是如何在C++中工作的
- C++将目录中的所有文件与::filesystem进行比较
- shell排序中的交换和比较
- 如何在C++中高效地构造随机骰子
- 高效简单的结构比较运算符
- MPI BMP 图像比较更高效
- 带有结构键的 std::map 的高效比较器
- 高效的浮点比较
- 如何以特定的方式高效地比较向量和数组