比较双精度的简单方法



我正在编写一个数字代码,需要在双精度数之间进行广泛(可能是快速)的比较。我比较两个数字A和B的方法是将A向左(或向右)移动一个,并检查结果是否比B大(或小)。如果是,两个双精度数是相同的。(负数或零数需要额外编码)。

这是比较函数:

#define S_
inline double s_l (double x){
    if(x>0){return 0.999999999*x;}
    else if(x<0){return 1.00000001*x;}
    else {return x-0.000000000001;}
}
inline double s_r (double x){
    if(x>0){return 1.00000001*x;}
    else if(x<0){return 0.999999999*x;}
    else{return x+0.000000000001;}
}
inline bool s_equal (double x,double y){
    if(x==y){return true;}
    else if(x<y && s_r(x)>y){return true;}
    else if(x>y && s_l(x)<y){return true;}
    else{return false;}
}
#endif

由于这是MonteCarlo算法的一部分,并且s_equal(x,y)被调用了数百万次,我想知道是否有更好或更快的方法来编写此代码,在简单的级别上可以理解

我做的是abs((x-y)/x) <1.0平台以及。

如果两个值都很大或很小,则需要除以x

我惊讶地发现,通过避免所有的双精度计算,可以显著提高速度:

#define S_L(x) (x)+((x)<0?1024:-1024)
#define S_R(x) (x)+((x)<0?-1024:1024)
#define S_EQUAL(x,y) (S_L(x)<(y) && S_R(x)>(y))
double foo;                                                                      
double bar;                                                                      
long *pfoo;                                                                      
long *pbar;                                                                      
pfoo = (long*)&foo;                                                              
pbar = (long*)&bar;          
double result1 = S_R(*pfoo);
double result2 = S_L(*pbar);
bool result3 = S_EQUAL(*pfoo, *pbar);

(在测试中,我对在-1M和1M之间随机生成的双精度对象进行操作,每次迭代使用不同的输入执行每个操作100M次。每个操作都在一个独立的循环中计时,比较系统时间,而不是墙时间。包括循环开销和随机数的生成,这个解决方案大约快了25%。)

一个警告:这里有很多依赖于你的硬件,你的双精度范围,你的优化器的行为,等等。当您开始对编译器进行事后评估时,这样的陷阱很常见。看到这对我来说有多快,我很震惊,因为我一直被告知,整数和浮点单位在硬件上是分开的,所以从一个到另一个的比特传输总是需要硬件内存操作。谁知道这对你有多管用呢。

你可能不得不玩弄一些神奇的数字(1024)来让它做你想做的事情——如果它可能的话。

如果您使用的是c++ 11,那么您可以使用新的math库函数,例如:

bool isgreater(float x, float y)

关于std::isgreater的更多文档可以在这里找到。

否则,boost中总是有is_equal。此外,SO已经有一堆相关的(不确定是否相同)问题,如这里,这里和这里的问题。

最新更新