我正在编写一个数字代码,需要在双精度数字之间进行广泛的(并且可能是快速的)比较。我比较两个数字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)被调用了数百万次,我想知道是否有更好或更快的方法对此进行编码,可以在简单的层次上理解。
答案 0 :(得分:0)
如果您正在使用C ++ 11,那么您可以使用新的math
库函数,例如:
bool isgreater(float x, float y)
有关std::isgreater
的更多文档可以here。
否则,提升中始终存在is_equal
。此外,SO已经有一堆相关(不确定是否相同)的问题,例如here,here和here。
答案 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)来让它去做你想要的事情 - 如果它甚至可能的话。