C++单调函数二分求根修改区间右端点触发段错误问题排查
问题核心原因
你代码的核心错误是二分查找的中点计算逻辑完全错误,其次是终止条件不合理,共同导致了死循环甚至崩溃:
- 中点计算错误
你当前计算pivot的代码是pivot = abs((b-a)/2);,这行代码得到的只是区间[a,b]的长度的一半,而不是区间的中点坐标。
正确的区间中点计算应该是:
pivot = a + (b - a) / 2;
你之前b=10的时候刚好能跑通纯粹是巧合:此时解x=2.5,在a始终为0的前几次循环里,你算的长度的一半刚好等于从0开始的中点,第二次循环就命中了返回条件,没暴露问题。
当b=100的时候,循环执行几次后a会被修改为大于0的值,此时你算的pivot会落在当前区间[a,b]之外,导致区间收缩逻辑完全失效,来回震荡进入死循环。
- 循环终止条件不合理
你当前终止条件是abs(b-a) != 0,double类型存在精度误差,两个浮点数几乎不可能完全相等,这个条件永远不会触发,就算中点计算正确,也大概率会陷入死循环。
正确的终止条件应该是判断区间长度小于你能接受的精度阈值,和你判断f(x)接近c的阈值对应即可:
while (abs(b-a) > 1e-6);
- 你观测到的段错误本质是死循环的衍生问题:死循环本身不会直接触发段错误,大概率是调试器检测到死循环后主动中断抛出的异常,或者是部分编译器对死循环的未定义行为优化导致的。
修复后的search函数示例
double search(double a, double b, double c, double (*f)(double x)) { double pivot; do { // 正确计算区间中点 pivot = a + (b - a) / 2; double val = f(pivot); if (abs(val - c) < 0.1) { return pivot; } else if (val > c) { b = pivot; } else { a = pivot; } // 用精度阈值判断终止 } while (abs(b-a) > 1e-6); // 循环结束后返回近似解即可 return a; }
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

