如何使迭代函数收敛至确定值?迭代函数收敛问题排查求助
迭代函数无法收敛的问题修复
我的迭代函数无法收敛至确定值,推测原因是每次新循环开始时未更新上一次计算的值,导致函数无法收敛,每次仅计算单一值。当前代码的问题在于无论输入何种f值,函数仅计算出对应的f0值,不会使用新值重复循环,直接返回f0。
原代码
import numpy as np Q = 62549.5 #gpm L = 52800 #ft a = (100 / 1.10) #Right side of energy balance Vis = 1.537*10**(-5) e = 0.0015 # in f = 0.008 ep = 0.00001 list = np.linspace(0.005, 1, 5) def friction(f): convergence = True while convergence: D = ((f*L*(Q**2))/(32.15*a))**(1/5) A = (3.14*(D/12)**2)/4 #ft^2 v = (Q/448.831)/A #ft/s Re = (v*(D/12))/Vis f0 = 0.25/(np.log10(e/(3.7*D) + 5.74/(Re**(9/10))))**2 convergence = abs((f0-f)/f0) < ep f = f0 break return f0 for f in list: print(friction(f))
问题诊断
- 致命问题:
break语句:循环体内的break会在第一次计算完成后直接终止while循环,导致迭代只执行一次,完全没有进入循环迭代的逻辑,自然无法收敛。 - 初始
convergence = True的设置逻辑冗余,且没有正确控制循环的终止条件。
修复后的代码
import numpy as np Q = 62549.5 # gpm L = 52800 # ft a = 100 / 1.10 # Right side of energy balance Vis = 1.537e-5 e = 0.0015 # in ep = 0.00001 test_list = np.linspace(0.005, 1, 5) # 避免使用内置类型名`list`作为变量 def friction(f): while True: # 基于当前f计算管径D D = ((f * L * (Q**2)) / (32.15 * a)) ** (1/5) # 计算过流面积(用np.pi替代硬编码3.14提升精度) A = (np.pi * (D/12)**2) / 4 # 流速计算 v = (Q / 448.831) / A # 雷诺数计算 Re = (v * (D/12)) / Vis # 计算新的摩擦系数f0 f0 = 0.25 / (np.log10(e/(3.7*D) + 5.74/(Re**(9/10))))**2 # 判断是否达到收敛条件,满足则退出循环 if abs((f0 - f)/f0) < ep: break # 更新f为当前计算的f0,用于下一次迭代 f = f0 return f0 # 遍历测试值并输出结果 for f_val in test_list: print(friction(f_val))
关键修改说明
- 移除
break语句:让循环可以根据收敛条件重复执行,真正实现迭代过程。 - 调整循环结构:改用
while True配合收敛条件判断退出,逻辑更直观清晰。 - 精度优化:用
np.pi代替硬编码的3.14,提升计算准确性。 - 变量名规范:将
list改为test_list,避免覆盖Python内置的list类型,防止潜在bug。
内容的提问来源于stack exchange,提问作者ChristianA.
相关产品推荐
相关产品推荐

