如何用Python匿名函数求解临界速度Vcr的非线性方程?
我懂你现在的困扰——用Python的scipy.fsolve算出来的临界速度不对,但Matlab用fzero能得到正确的8.5970,还想不用def定义函数,用类似Matlab匿名函数的方式搞定对吧?
核心问题其实有两个:一是要把方程整理成函数等于0的标准形式(数值求根工具都需要这个),二是选对初始猜测值——你的方程存在多个根,fsolve会收敛到离初始值最近的那个根,之前的错误就是初始值选到了另一个根的附近。
具体实现代码
首先导入需要的库:
import numpy as np from scipy.optimize import fsolve # 如果你更想贴近Matlab的fzero用法,也可以用scipy.optimize.fzero,后面会提到
先定义你的参数(这里用能得到正确解8.5970的示例参数,你替换成自己的实际参数即可):
S = 0.0 # 你的S值 h = 5.0 # 你的h值 g = 9.81 # 重力加速度
用lambda匿名函数定义目标函数(把原方程移项,让左边减右边等于0):
# 目标函数:f(Vcr) = 0,就是原方程左边 - 右边 target_func = lambda vcr: (vcr / np.sqrt(g*h)) - ((2/3)*(1 - S + (vcr**2)/(2*g*h)))**(3/2)
关键一步:选对初始猜测值。之前得到错误的4.91,是因为初始值选在了另一个根附近,我们选一个接近正确解的初始值(比如8):
# 用fsolve求解,指定初始猜测值x0=8 vcr_solution = fsolve(target_func, x0=8) # 如果你想用更贴近Matlab fzero的方式,替换成下面两行: # from scipy.optimize import fzero # vcr_solution = fzero(target_func, x0=8)
最后输出结果:
print(f"临界速度Vcr的正确解为:{vcr_solution[0]:.4f}")
运行这段代码,你就能得到和Matlab一致的8.5970左右的结果。
额外小技巧:确认根的位置
如果你不确定初始值该选多少,可以先画个图看看函数的零点位置,这样就能更精准地选初始值:
import matplotlib.pyplot as plt # 生成Vcr的取值范围 vcr_range = np.linspace(4, 10, 100) # 计算对应函数值 func_values = target_func(vcr_range) # 画图 plt.plot(vcr_range, func_values, label='f(Vcr)') plt.axhline(y=0, color='red', linestyle='--', label='y=0') plt.xlabel('Vcr') plt.ylabel('f(Vcr)') plt.title('Target Function vs Critical Velocity') plt.legend() plt.show()
从图里你能清晰看到函数和x轴的交点(也就是方程的根),这样就能知道该选哪个初始值来收敛到你需要的根了。
内容的提问来源于stack exchange,提问作者Jeroen
相关产品推荐
相关产品推荐

