You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用scipy.fsolve求解x_Prime遇无解错误,但绘图显示存在解

scipy.optimize.fsolve求解方程失败的原因及解决办法

问题核心

你使用fsolve求解方程时触发无解错误,但绘图明确显示解存在,根源在于初始值选择不当,叠加函数特性导致迭代无法收敛到目标根。

关键数值分析

先计算方程中的固定参数值:

  • c_val=100时,f_NFW_val = math.log(1+100) - 100/(1+100) ≈ 3.625,因此1/f_NFW_val≈0.2759
  • 目标方程eqn(x_Prime)=0等价于:0.2759*(math.log(1+100x)/x - 100/(1+100x)) = 3.0608
  • 当x=1时,右侧表达式的值≈1,远小于3.06,因此eqn(1)=3.06-1=2.06>0
  • 根位于x≈0.163处,此时右侧表达式恰好等于3.06,满足eqn(x)=0

为什么fsolve从x=1出发找不到根?

fsolve默认采用牛顿-拉夫逊法,该方法的收敛依赖两个条件:

  1. 初始猜测值需足够靠近根
  2. 函数在初始值附近的导数特性稳定

你的函数在x>0.163区间单调递减,从x=1到x=0.163,函数值从1升至3.06,但牛顿法从x=1出发时,由于初始值离根过远,迭代过程中可能因斜率变化导致步长不合理,甚至向x=0方向偏移(此时函数趋近于0,eqn(x)趋近于3.06,完全偏离目标根),最终触发收敛失败。

解决办法

方法1:调整初始值到根附近

直接将初始猜测值改为靠近根的数值(比如0.2),这是最可靠的方案:

import math
import scipy.optimize as so

c_val = 100
f_NFW_val = math.log(1+c_val)-c_val/(1+c_val)

psi_prime = 3.0608421399604424

eqn = lambda x_Prime: psi_prime  -  1/f_NFW_val * ( math.log(1+c_val*x_Prime)/x_Prime - c_val/(1+c_val*x_Prime) )
sol = so.fsolve(eqn, 0.2)[0]
print(sol)  # 输出≈0.1633804055843348,与绘图显示的根一致

方法2:使用区间搜索类方法

如果无法确定根的大致位置,可改用支持区间搜索的root_scalar(比如二分法),无需依赖初始值的精度:

import math
from scipy.optimize import root_scalar

c_val = 100
f_NFW_val = math.log(1+c_val)-c_val/(1+c_val)

psi_prime = 3.0608421399604424

eqn = lambda x_Prime: psi_prime  -  1/f_NFW_val * ( math.log(1+c_val*x_Prime)/x_Prime - c_val/(1+c_val*x_Prime) )
res = root_scalar(eqn, bracket=[0.1, 0.3], method='bisect')
sol = res.root
print(sol)

方法3:调整fsolve的迭代参数(不推荐)

若坚持使用初始值1,可通过增大迭代次数、调整容差尝试收敛,但效率较低且不稳定:

sol = so.fsolve(eqn, 1, maxfev=1000, xtol=1e-8)[0]

内容的提问来源于stack exchange,提问作者ellipse314

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:45:01