如何防止 sqrt 中的溢出
How to prevent overflow in 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);
或者根据您的需要进一步拆分。
如果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说的去做。
相关文章:
- 'short int'持有的值溢出,但"自动"不会溢出?
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 大于65535的C++数组[size]引发不一致的溢出
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- C++中无符号字符溢出
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 整数溢出,最大值为 pow(10,19)
- 获取隐式转换溢出从无符号到已签名的警告
- 使用 strcat 获取缓冲区溢出错误
- LeetCode 1:两和 - 地址清理器:堆缓冲区溢出地址
- 如果我重新定义 sqrt 函数,为什么使用 std::sqrt 失败?
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 使用未声明的标识符"sqrt"?
- 在 SVM-Struct 中未定义对 sqrt 的引用(已使用 -lm)
- C++ 对象数组堆栈溢出
- 使用提升::lexical_cast捕获溢出
- C++ Unordered_set功能中的溢出
- 如何防止 sqrt 中的溢出