比较双打的简单方法

时间:2013-04-23 23:21:53

标签: c++ compare double floating

我正在编写一个数字代码,需要在双精度数字之间进行广泛的(并且可能是快速的)比较。我比较两个数字A和B的解决方案涉及通过epsilon将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)被调用了数百万次,我想知道是否有更好或更快的方法对此进行编码,可以在简单的层次上理解。

3 个答案:

答案 0 :(得分:0)

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

bool isgreater(float x, float y)

有关std::isgreater的更多文档可以here

否则,提升中始终存在is_equal。此外,SO已经有一堆相关(不确定是否相同)的问题,例如hereherehere

答案 1 :(得分:0)

我做的事情就像abs((x-y)/ x)&lt; 1.0e-10。

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

答案 2 :(得分:0)

我很惊讶地发现通过避免所有双精度数学来获得显着的加速:

#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次,每次迭代不同的输入。每个操作都在一个独立的循环中定时,比较系统时间 - 而不是墙壁时间。 strong>包括循环开销和随机数生成,此解决方案的速度提高了约25%。)

警告:你的硬件上存在很多依赖关系,你的双打范围,优化器的行为等等。当你开始二次猜测你的编译器时,这种陷阱是司空见惯的。我很震惊地看到这对我来说有多快,因为我总是被告知整数和浮点单元在硬件上保持如此独立,以至于从一个到另一个的位传输总是需要硬件存储器操作。谁知道这对你有多好。

你可能不得不玩一些神奇的数字(1024s)来让它去做你想要的事情 - 如果它甚至可能的话。