为什么我用二分法O(logn)实现的求平方根代码报浮点异常
问题根因排查
你代码触发浮点异常的核心原因有三个:
- 第一,除以0触发浮点异常:当x输入为0的时候,首次循环mid计算值为0,后续执行
x/mid操作时直接触发除0错误,属于典型的浮点异常触发场景。 - 第二,错误的强制类型转换导致溢出截断:你多次把
long long类型的值强制转为int,比如(int)(l+r)/2、(int)x/mid,如果输入的x值大于int类型的最大值(通常32位int最大值是2^31-1),强制转换会发生溢出截断,得到错误的数值,极端场景下也会触发计算异常。 - 第三,
mid*mid计算存在溢出风险:当mid值较大时,mid的平方会超出long long的承载范围,溢出后得到的错误值会导致二分逻辑判断完全错误。
修复后的代码
long long int floorSqrt(long long int x) { // 边界情况特殊处理 if (x == 0 || x == 1) return x; long long int l = 1, r = x, ans; while (l <= r) { // 避免l+r溢出,不做强制类型转换 long long int mid = l + (r - l)/2; // 不用mid*mid避免溢出,直接用mid和x/mid比较 if (mid == x / mid) { return mid; } if (mid > x / mid) { r = mid - 1; } else { l = mid + 1; ans = mid; } } return ans; }
关键修复点说明
- 提前处理x=0、x=1的边界场景,避免后续出现mid=0的除0操作
- 所有数值计算全程使用
long long类型,删除多余的int强制转换,避免截断溢出 - mid计算改用
l + (r-l)/2的写法,避免l+r直接相加超出long long范围溢出 - 去掉
mid*mid的计算逻辑,直接用mid和x/mid的比较完成判断,彻底规避平方溢出问题 - 合并判断分支,避免重复计算x/mid,同时保证逻辑正确性
内容的提问来源于stack exchange,提问作者chirag verma
相关产品推荐
相关产品推荐

