我有代码
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 太大,即使输出应该很小,事情也会溢出。有没有解决的办法?
以代数方式拆分平方根的参数,也许?:
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);
您可以对此进行优化,但这只是为了说明这一点。
我相信在 x 或 y 较大时,-1 可以忽略 wrt (x*x)*(y*y) ...并且由于您的函数返回 long long,因此浮点精度无关紧要。
您可以检查 x 或 y 是否大,因此,您可以选择忽略 -1 并按照 Chris 或 Rob 所说的那样做。