请求将NPV计算的for循环转为递归函数,求递归原理讲解
把NPV循环代码转成递归函数 + 递归入门讲解
递归版NPV代码
rate, cashflows = 0.05, [-1100, 300, 450, 800] def npv_recursive(rate, cashflows): def helper(i, current_npv): # 基线条件:所有现金流处理完毕,停止递归 if i == len(cashflows): return # 计算当前现金流的现值,累加到已有NPV上 new_npv = current_npv + cashflows[i] / (1 + rate)**i print(round(new_npv, 3)) # 递归调用:处理下一个现金流,更新索引和累计NPV helper(i + 1, new_npv) # 初始调用:从第0个现金流开始,初始累计NPV为0 helper(0, 0) # 测试调用 npv_recursive(rate, cashflows)
递归核心知识讲解
递归就是函数自己调用自己,把一个大问题拆成一个个和原问题逻辑一致的小问题,直到遇到“不能再拆”的基线条件,就停止调用并返回结果。
递归的两个必备要素
- 基线条件:必须有明确的终止点,否则函数会无限调用自己,直接撑爆内存栈。比如上面代码里的
if i == len(cashflows): return,当所有现金流都处理完,就停止递归。 - 递归步骤:把当前问题拆解成更小的子问题,调用自身解决子问题,再把子问题的结果组合起来。比如这里,处理第
i个现金流的问题,拆解成“先算第i个的现值加到累计值里,再处理第i+1个现金流”。
对应原循环的逻辑对比
原循环是从i=0到i=3,手动跟踪累计NPV和当前索引;递归版本用helper函数自动维护两个状态:
i:当前处理到第几个现金流current_npv:到当前为止累计的NPV值
每次递归调用都会完成三件事:
- 检查是否处理完所有现金流(触发基线条件则停止)
- 计算当前现金流的现值,更新累计NPV并打印
- 调用自己处理下一个现金流
递归与循环的优劣
- 递归代码更贴合问题的自然逻辑,写法简洁,但如果递归深度过大(比如现金流有几万个),会占用更多栈内存,甚至触发栈溢出错误。
- 循环的内存占用更稳定,但需要手动跟踪状态(比如原循环里的
NPV变量和i索引)。
内容的提问来源于stack exchange,提问作者user9110693
相关产品推荐
相关产品推荐

