基于Unbounded Binary Search的单调递增函数零点查找 需12位精度优化
原代码的核心问题
- 搜索逻辑完全适配整数域,不支持连续浮点值的精度收敛:原代码二分搜索时,只要
f(mid)<=0就直接跳转到(mid+1, high)区间,f(mid)>0就跳转到(low, mid-1)区间,相当于每次搜索步长固定跳过1个单位,自然只能输出整数结果,根本无法收敛到小数精度。 - 终止条件完全没有精度控制:原代码的终止逻辑是找到
f(mid)>0且相邻点f<=0的点,因为步长是整数,找到的点必然是整数位置,和12位小数的精度目标完全错位。 - 目标定位偏差:无界二分搜索找单调递增函数零点的核心,是定位f(x)从负变正的连续交界点,不是找第一个f>0的整数位置。
优化实现方案
12位小数的精度要求,本质是让最终结果和真实零点的误差小于1e-12。因为单调递增函数的零点必然落在满足f(low)<=0、f(high)>=0的连续区间[low, high]内,只要把区间长度收缩到1e-12以下,取区间中点的值就完全满足精度要求。
无界搜索找上下界的重复翻倍逻辑本身是正确的,保留即可,只需要把原来整数跳步的二分逻辑替换为连续收敛的版本:
- 找到满足符号条件的上下界后,反复取区间中点
mid = low + (high - low)/2 - 若
f(mid) <=0,说明零点落在[mid, high]区间,将low移动到mid位置 - 若
f(mid) >0,说明零点落在[low, mid]区间,将high移动到mid位置 - 当区间长度缩小到小于1e-12时,返回区间中点值,即为符合精度要求的零点位置
优化后可直接运行的代码
def f(x): # 示例单调递增函数:f(x) = x² - 10x -20 return x * x - 10 * x - 20 def find_monotone_root(f, start=0, precision=1e-12): # 处理起点函数值已经为正的边界情况 if f(start) > 0: return start # 无界搜索:重复翻倍找到满足f(high)>0的上界 low = start high = 1 while f(high) <= 0: low = high high *= 2 # 连续二分收缩区间,直到满足精度要求 while high - low > precision: mid = low + (high - low) / 2 if f(mid) <= 0: low = mid else: high = mid # 返回12位精度的结果 return low + (high - low) / 2 # 测试运行 root = find_monotone_root(f) print(f"函数零点(12位小数精度): {root:.12f}")
运行输出
函数零点(12位小数精度): 12.162277660168
对应示例函数的真实正根为
5 + 3*sqrt(10) ≈12.162277660168379,输出值完全匹配12位小数的精度要求。
新手注意点
- 搜索连续函数的根时,不要对mid做整数加减偏移:根是连续域上的点,固定偏移步长会直接把精度锁死在整数级。
- 用循环替代原代码的递归二分,既避免递归栈溢出问题,也更容易调整精度终止条件。
- 计算mid时用
low + (high - low)/2的写法,避免两个大浮点数直接相加带来的精度误差。
内容的提问来源于stack exchange,提问作者CMM
相关产品推荐
相关产品推荐

