C++ 如何防止sqrt中的溢出?
我有密码C++ 如何防止sqrt中的溢出?,c++,math,sqrt,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 ); } 但是如果x或y太大,即使输出应该很小,也会溢出。有办法解决这个问题吗 也许可以用代数方法将平方根的参数拆分为: return sqrt((3*x*x+1)/2) * sqrt((6*y*y-5)/2); 或者根据您的需要
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可以忽略w.r.t(x*x)*(y*y)。。。由于函数返回long-long,因此浮点精度无关紧要
你可以检查x或y是否大,因此,你可以选择忽略-1,按照Chris或Rob说的去做。你需要一个多精确的答案?重命名你的函数…这是非常不明显的它应该做什么。还有templatetypedef说了些什么。@Brendan:你有没有想过这可能是某些礼仪规范的一部分,而且对
f
使用实名可能会违反OP的保密协议?例如,f
可以。@Brendan:…或者它只是作为一个示例,在本例中,函数名完全不相关?sqrt
不会溢出。当然你一定是指计算结果。注意:由于整数除法,sqrt(3/2)
=sqrt(1)
=1
@Robᵩ 说得好,我换了一种更具符号性的符号,但我会纠正这个C/C++的错误。@Againsticilian同样的概念也适用。我不能将它分为两个产品,因为我有一个-1,很幸运,我已经尝试了Wolfram。如果我能做到的话,我就不会把问题贴出来了!:)