如何防止sqrt溢出?

MyN*_*han 3 c++ math sqrt

我有代码

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

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

Chr*_* A. 8

可能代数地将平方根的参数分开吗?

return sqrt((3*x*x+1)/2) * sqrt((6*y*y-5)/2);
Run Code Online (Sandbox Code Playgroud)

或者根据您的需要进一步分解.

如果x足够大,你可以忽略+1并制作第一个术语:

sqrt((3*x*x)/2) = fabs(x) * sqrt(3.0/2.0)
Run Code Online (Sandbox Code Playgroud)

y第二个学期一样,制作它

sqrt((6*y*y)/2) = fabs(y) * sqrt(3.0);
Run Code Online (Sandbox Code Playgroud)

编辑:OP编辑后他的问题是:

return sqrt(((3*x*x+1)*(6*y*y-5)-1)/4);  
Run Code Online (Sandbox Code Playgroud)

事实上,你可以将事情分开.你必须要小心一些.底线是,如果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); 
Run Code Online (Sandbox Code Playgroud)

你可以对此进行优化,但这只是为了表明这一点.