二分法(Bisection Method)C实现的疏漏排查与正确性验证
二分法实现代码的疏漏梳理
对照二分法的标准执行流程,你当前编写的代码存在多处会直接导致算法失效的逻辑问题,具体如下:
- 缺失前置区间合法性校验
二分法能正常工作的核心前提是待搜索区间[a,b]的两个端点对应的函数值异号(即f(a) * f(b) < 0),保证区间内至少存在一个实根。当前代码完全没有做这个校验,如果输入的a、b端点函数值同号,算法从根源上不满足适用条件,后续计算没有任何意义。 - 循环终止条件完全偏离误差定义
你当前写的循环判断条件是while (abs(mid) > e),本质上是在判断mid的绝对值是否大于误差阈值,相当于默认要找的根就是x=0,完全没有匹配二分法的误差逻辑:二分法的误差是近似根和真实根的距离,因为每迭代一次搜索区间就会折半,当当前搜索区间的长度b - a的绝对值小于给定的误差e时,区间内任意点作为近似根的误差都不会超过e,这才是正确的终止判断依据。 - 迭代逻辑的赋值方向完全写反
你在循环中判断完f(mid)的符号后,写的是把a或者b的值直接赋给mid(mid = a/mid = b),而不是根据符号更新区间的左右边界。这会导致mid直接跳转到固定的区间端点,完全没有逐步缩小区间范围的过程,和二分法的迭代逻辑完全相悖,大概率会造成死循环。
举个实际运行的例子:用你写的测试函数func,假设传入a=3、b=4,e=0.001,第一次计算mid=3.5,f(mid)=0.75>0,按现有代码逻辑会直接把mid赋值为b=4;下一轮循环判断mid=4,f(mid)=3>0,又把mid赋值为b=4,从此陷入无限循环永远无法退出。
正确的缩区间逻辑是:判断f(a)和f(mid)的符号,如果二者同号,说明根不在左半区间,就把左边界a更新为mid;如果二者异号,说明根在左半区间,就把右边界b更新为mid,之后重新计算新的区间中点进入下一轮迭代。 - 浮点数绝对值函数使用错误
C标准库中的abs()函数是针对int类型设计的,传入double类型的参数时会先把值截断为整数再取绝对值,直接导致计算结果错误。针对浮点数的取绝对值操作,应该使用fabs()函数。 - 中点计算存在溢出风险
当前用(a + b) / 2计算中点的写法,在a、b都是数值较大的double类型时,二者求和的结果可能超出double的取值范围造成溢出。更安全的写法是a + (b - a) / 2,从计算逻辑上避免大数求和的溢出问题。
额外提醒:哪怕修正了上述所有边界赋值的问题,你的代码也遗漏了每轮迭代结束后重新计算新中点的步骤,缺少这个环节的循环会完全失去迭代的意义。
内容的提问来源于stack exchange,提问作者Athhhelon
相关产品推荐
相关产品推荐

