我有代码
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太大,即使输出应该很小,东西也会溢出。有没有解决的办法?
答案 0 :(得分: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);
你可以对此进行优化,但这只是为了表明这一点。
答案 1 :(得分:0)
我相信在大的x或y,-1可以忽略wrt(x * x)*(y * y)...并且由于你的函数返回long long,浮点精度无关紧要。
你可以检查x或y是否大,因此,你可以选择忽略-1并按照Chris或Rob的说法进行操作。