核心思想
如果函数
在
上连续,并且满足:

那么说明
和
异号。根据连续函数的零点存在定理,区间
内至少存在一个根:

理论刨析
定初始区间
以函数为为例 。
我们取初始区间为
,二分法要求函数在区间两端异号,即:

现在取:

计算左端点函数值:

计算右端点函数值:

因此:

所以,区间
满足二分法的使用条件,说明该区间内至少存在一个根:

二分法
第一次二分
初始区间为:
![[a_0,b_0]=[1,6]](2026-06-11z4keccxuzmj.png)
中点为:

计算中点函数值:

因为:

所以:

因此根位于左半区间:
![[a_1,b_1]=[1,3.5]](2026-06-11dmbmcx0hs0m.png)
第二次二分
当前区间为:
![[a_1,b_1]=[1,3.5]](2026-06-11dmbmcx0hs0m.png)
中点为:

计算函数值:

因为:

所以:

因此根位于右半区间:
![[a_2,b_2]=[2.25,3.5]](2026-06-11xswzkimc2fa.png)
第三次二分
当前区间为:
![[a_2,b_2]=[2.25,3.5]](2026-06-11xswzkimc2fa.png)
中点为:

计算函数值:

因为:

所以根位于右半区间:
![[a_3,b_3]=[2.875,3.5]](2026-06-11s2vsvczrdxd.png)
当我们不断迭代的时候,区间
会不断收敛到真实值附近。但是我们不可能无限迭代。
终止条件
1.函数值足够接近 0
当中点
的函数值已经非常接近 0 时,可以停止:

其中
是我们设定的误差精度,例如:

也就是说,只要:

就认为当前中点
已经可以作为方程的近似根。
2. 区间长度足够小
二分法每次都会把区间缩小一半。当区间已经非常短时,说明根已经被锁定在一个很小的范围内,此时也可以停止。
停止条件可以写为:

这里的含义是:当前中点
与真实根
的最大误差已经小于
因为:
所以有:

因此,只要:

就可以保证近似根的误差小于设定精度。
3. 达到最大迭代次数
为了防止程序出现异常循环,实际编程时通常还会设置最大迭代次数:

例如:

如果循环次数达到 100 次,即使还没有满足精度条件,也强制停止。
二分法就是利用连续函数的变号性质,通过“取中点—判符号—缩区间”的方式逐步逼近方程的根。
案例实操
一、for循环版本
结束条件是:达到最大迭代次数。
# ============================================================
# 二分法求根:for 循环版本
# 结束条件:达到最大迭代次数
# 方程:f(x) = x^2 + 2x – 15
# 初始区间:[1, 6]
# ============================================================
# 1. 定义目标函数
f <- function(x) {
return(x^2 + 2 * x – 15)
}
# 2. 设置初始区间
a <- 1
b <- 6
# 3. 检查初始区间是否满足二分法条件
if (f(a) * f(b) > 0) {
stop("初始区间两端函数值同号,不能使用二分法。")
}
# 4. 设置最大迭代次数
max_iter <- 30
# 5. 创建结果保存表
result_for <- data.frame(
iteration = integer(),
a = numeric(),
b = numeric(),
c = numeric(),
f_c = numeric()
)
# 6. for 循环进行二分迭代
for (k in 1:max_iter) {
# 计算中点
c <- (a + b) / 2
# 计算中点函数值
f_c <- f(c)
# 保存当前迭代结果
result_for <- rbind(
result_for,
data.frame(
iteration = k,
a = a,
b = b,
c = c,
f_c = f_c
)
)
# 判断根所在区间
if (f(a) * f_c < 0) {
b <- c
} else {
a <- c
}
}
# 7. 输出迭代结果
print(result_for)
# 8. 输出最终近似根
root_for <- c
cat("for循环版本的近似根为:", root_for, "\\n")
cat("近似根处的函数值为:", f(root_for), "\\n")
cat("总迭代次数为:", max_iter, "\\n")
二、while循环版本
结束条件是:当中点函数值足够接近 0 时停止。
# ============================================================
# 二分法求根:while 循环版本
# 结束条件:函数值精度 |f(c)| < epsilon
# 方程:f(x) = x^2 + 2x – 15
# 初始区间:[1, 6]
# ============================================================
# 1. 定义目标函数
f <- function(x) {
return(x^2 + 2 * x – 15)
}
# 2. 设置初始区间
a <- 1
b <- 6
# 3. 检查初始区间是否满足二分法条件
if (f(a) * f(b) > 0) {
stop("初始区间两端函数值同号,不能使用二分法。")
}
# 4. 设置精度
epsilon <- 1e-6
# 5. 初始化变量
k <- 0
c <- (a + b) / 2
f_c <- f(c)
# 6. 创建结果保存表
result_while <- data.frame(
iteration = integer(),
a = numeric(),
b = numeric(),
c = numeric(),
f_c = numeric()
)
# 7. while 循环进行二分迭代
while (abs(f_c) >= epsilon) {
# 迭代次数加 1
k <- k + 1
# 保存当前迭代结果
result_while <- rbind(
result_while,
data.frame(
iteration = k,
a = a,
b = b,
c = c,
f_c = f_c
)
)
# 判断根所在区间
if (f(a) * f_c < 0) {
b <- c
} else {
a <- c
}
# 重新计算新区间中点
c <- (a + b) / 2
# 重新计算中点函数值
f_c <- f(c)
}
# 8. 保存最后一次满足精度的结果
result_while <- rbind(
result_while,
data.frame(
iteration = k + 1,
a = a,
b = b,
c = c,
f_c = f_c
)
)
# 9. 输出迭代结果
print(result_while)
# 10. 输出最终近似根
root_while <- c
cat("while循环版本的近似根为:", root_while, "\\n")
cat("近似根处的函数值为:", f(root_while), "\\n")
cat("总迭代次数为:", k + 1, "\\n")
cat("设定精度为:", epsilon, "\\n")


