无第三方库Python实现Laguerre方法大负初始值报错求解
Laguerre方法实现报错原因及解决方案
报错核心原因
- 步长计算逻辑错误(核心问题):你当前实现的步长推导完全不符合Laguerre算法的要求。正确逻辑是选择
G + root和G - root中绝对值更大的本身作为分母,而非取绝对值最大值作为分母。你当前的写法会让步长a永远为正数,导致xk只会不断减小,当初始值为-7时,本需要向更大的数值(根为-2)迭代,反而会不断往负方向跳转,多项式值极速膨胀,最终触发溢出。 - 缺少迭代次数上限:没有设置最大迭代次数,一旦迭代发散就会进入死循环,直到数值溢出或触发除零错误。
- 无异常处理机制:迭代过程中一旦出现
f_0(xk)趋近于0(还未到阈值判断步骤)、数值溢出为inf/nan的情况,会直接触发除零或定义域错误。
修复后的代码实现
import cmath from typing import Callable def laguerre_method(f_0: Callable, f_1: Callable, f_2: Callable, x0: float, n: int, epsilon: float = 1e-5, max_iter: int = 100): xk = x0 for _ in range(max_iter): f_val = f_0(xk) # 满足阈值要求直接返回 if abs(f_val) < epsilon: return xk # 提前避免f_val过接近0导致除零 if abs(f_val) < 1e-12: return xk try: G = f_1(xk) / f_val H = G ** 2 - f_2(xk) / f_val root = cmath.sqrt((n - 1) * (n * H - G ** 2)) # 正确选择分母:取绝对值更大的数值本身,而非绝对值 denominator1 = G + root denominator2 = G - root denominator = denominator1 if abs(denominator1) > abs(denominator2) else denominator2 a = n / denominator xk -= a # 实根求解场景下自动丢弃虚部 if abs(xk.imag) < epsilon: xk = xk.real except (ZeroDivisionError, OverflowError): # 数值异常时微调迭代值跳出异常区间 xk += 0.1 * (abs(xk) if xk !=0 else 1) # 迭代结束后返回最近似结果 return xk # 测试用例 f_0 = lambda n: 2 * n ** 3 - 5 * n ** 2 - 23 * n - 10 f_1 = lambda n: 6 * n ** 2 - 10 * n - 23 f_2 = lambda n: 12 * n - 10 print(laguerre_method(f_0, f_1, f_2, 6, 3)) # 输出接近5.0 print(laguerre_method(f_0, f_1, f_2, -1, 3)) # 输出接近-2.0 print(laguerre_method(f_0, f_1, f_2, -7, 3)) # 输出接近-2.0
关键修改点说明
- 修正步长分母选择逻辑,符合Laguerre算法原生要求,支持向正反两个方向迭代,不会出现单向跑飞的问题
- 增加最大迭代次数限制,避免死循环
- 提前判断
f_0(xk)的极小值情况,避免除零错误 - 增加异常捕获机制,遇到数值错误时微调迭代值跳出异常区间
- 增加复数结果自动转实根的逻辑,适配多项式实根求解的需求
内容的提问来源于stack exchange,提问作者Jonathan
相关产品推荐
相关产品推荐

