Progress或Python实现Excel Solver等价功能求解公式未知参数B8
两种环境下的B8参数求解实现方案
这个问题本质是单变量连续非线性方程的求根问题,不需要依赖Excel Solver,在Python、Progress OpenEdge环境下都可以独立实现,求解精度和Excel Solver基本一致。
前置准备:先明确方程对应关系
把原Excel公式做简化整理,降低计算复杂度:
- 已知固定量:目标计算结果(示例值150)、常量单元格B11、常量单元格B14
- 待求未知量:B8
- 公式简化逻辑:令
r = (100 - B8)/200,原公式本质是典型的现金流现值计算式,求解r即可反推B8 = 100 - 200*r,计算过程中只要规避r=0(即B8=100)的除零边界即可。
Python 实现方案
使用scipy内置的鲁棒求根算法即可快速得到稳定解,无需手动实现复杂迭代逻辑。
实现步骤
- 安装依赖:
pip install scipy numpy - 代入自己的固定常量值,运行如下代码:
import numpy as np from scipy.optimize import brentq # 替换为你实际业务中的固定常量值 target_output = 150 # 公式的已知最终计算结果 B11_const = 20 # 固定B11值 B14_const = 5 # 固定B14值 def root_equation(B8): # 处理B8=100时的除零边界 if np.isclose(B8, 100): return B11_const * B14_const + 100 - target_output r = (100 - B8) / 200 discount = 1 / (1 + r) annuity_value = B11_const * (1 - discount ** B14_const) / r terminal_value = 100 * (discount ** B14_const) return annuity_value + terminal_value - target_output # 在合理业务区间(B8取值0-100)内求解 B8_result = brentq(root_equation, a=0, b=100) print(f"求解得到的B8值为:{B8_result:.4f}")
方案说明
brentq算法结合了二分法、割线法的优势,只要给定的求解区间两端函数值异号,就能稳定收敛到正确解,不存在梯度类算法容易陷入局部最优的问题,计算结果和Excel Solver的差异通常小于1e-6。
Progress OpenEdge 实现方案
Progress没有内置的成熟求根工具,可以基于二分法实现纯ABL的求解逻辑,代码量少、稳定性高,无需引入外部依赖。
实现逻辑
- 划定合理的B8求解区间(通常取0-100,匹配业务实际取值范围)
- 单独实现和Excel公式计算逻辑完全一致的函数,支持传入任意B8值计算对应输出结果
- 迭代缩小区间范围,直到求解精度满足业务要求(可设置为和Excel Solver一致的0.0001级精度)
可直接运行的代码片段
/* 替换为实际业务常量 */ DEFINE VARIABLE target_output AS DECIMAL NO-UNDO INITIAL 150. DEFINE VARIABLE B11_const AS DECIMAL NO-UNDO INITIAL 20. DEFINE VARIABLE B14_const AS INTEGER NO-UNDO INITIAL 5. DEFINE VARIABLE low_bound AS DECIMAL NO-UNDO INITIAL 0. DEFINE VARIABLE high_bound AS DECIMAL NO-UNDO INITIAL 100. DEFINE VARIABLE mid_B8 AS DECIMAL NO-UNDO. DEFINE VARIABLE calc_diff AS DECIMAL NO-UNDO. DEFINE VARIABLE precision AS DECIMAL NO-UNDO INITIAL 0.00001. /* 按Excel公式逻辑计算给定B8对应的输出值 */ FUNCTION calc_excel_formula RETURNS DECIMAL (INPUT B8_val AS DECIMAL): DEFINE VARIABLE r AS DECIMAL NO-UNDO. DEFINE VARIABLE discount AS DECIMAL NO-UNDO. r = (100 - B8_val) / 200. /* 处理r=0的除零边界 */ IF r = 0 THEN RETURN B11_const * B14_const + 100. discount = 1 / (1 + r). RETURN ( B11_const * (1 - discount ** B14_const) / r + 100 * (discount ** B14_const) ). END. /* 二分迭代求解 */ REPEAT: mid_B8 = (low_bound + high_bound) / 2. calc_diff = calc_excel_formula(mid_B8) - target_output. /* 精度达标就退出循环 */ IF ABS(high_bound - low_bound) < precision THEN LEAVE. /* 按差值方向缩小区间 */ IF calc_diff > 0 THEN low_bound = mid_B8. ELSE high_bound = mid_B8. END. MESSAGE "求解得到的B8值为:" mid_B8 VIEW-AS ALERT-BOX INFORMATION.
方案说明
二分法的收敛过程完全可控,不会出现算法跑飞的情况,最终求解结果和Excel Solver的误差可以控制在1e-4以内,完全满足日常业务计算的精度要求。
注意事项
- 求解前先确认给定的目标值是否在函数的取值范围内:如果B8在0-100的合法区间内,公式的最大/最小输出都小于目标值,就会出现无解情况,需要先核对输入常量是否正确。
- 务必处理B8=100时的除零边界,避免程序触发运行时错误。
- 求解区间不要设置得过宽,尽量匹配业务实际的B8取值范围,避免求到不符合业务逻辑的非预期解。
内容的提问来源于stack exchange,提问作者Radek
相关产品推荐
相关产品推荐

