5

我有代码

unsigned long long f(unsigned long long x, unsigned long long y){
   return sqrt( ( (5*x*x + 1) * (5*y*y +1) - 1 ) / 4 );         
}

但是如果 x 或 y 太大,即使输出应该很小,事情也会溢出。有没有解决的办法?

4

2 回答 2

8

以代数方式拆分平方根的参数,也许?:

return sqrt((3*x*x+1)/2) * sqrt((6*y*y-5)/2);

或根据您的需要进一步拆分。

如果x足够大,您可以忽略+1并进行第一项:

sqrt((3*x*x)/2) = fabs(x) * sqrt(3.0/2.0)

y第二个任期类似,使其

sqrt((6*y*y)/2) = fabs(y) * sqrt(3.0);

编辑:在 OP 将他的问题编辑为:

return sqrt(((3*x*x+1)*(6*y*y-5)-1)/4);  

事实上,你可以把事情分开。你只需要更加小心一点。底线是,如果x真的很大,那么+1可以忽略。如果y真的很大那么-5可以忽略。如果两者(3*x*x+1)都是(6*y*y-5)正的,并且两者都很大,那么-1可以忽略。您可以使用这些技巧和一些额外的周边逻辑来进一步分解它。像这样:

 if(fabs(x) > BIGNUMBER && fabs(y) > BIGNUMBER)
 {
     return fabs(x) * fabs(y) * sqrt(18.0/4.0);
 }
 if(fabs(x) > BIGNUMBER && fabs(y) > 1.0)  // x big and y term positive
 {
     return fabs(x) * sqrt(6*y*y-5) * sqrt(3.0/2.0);
 }
 if(fabs(y) > BIGNUMBER)  // x term positive and y big
 {
     return sqrt(3*x*x+1) * fabs(y) * sqrt(6.0/2.0);
 }
 return sqrt(((3*x*x+1)*(6*y*y-5)-1)/4); 

您可以对此进行优化,但这只是为了说明这一点。

于 2012-06-26T20:42:33.380 回答
0

我相信在 x 或 y 较大时,-1 可以忽略 wrt (x*x)*(y*y) ...并且由于您的函数返回 long long,因此浮点精度无关紧要。

您可以检查 x 或 y 是否大,因此,您可以选择忽略 -1 并按照 Chris 或 Rob 所说的那样做。

于 2012-06-26T20:59:27.467 回答