首页 > 解决方案 > 使用近似解和二分搜索

问题描述

我想明确指出,这个问题来自 EDX python course for Intro to Comp Sci(免费在线课程),我在网上看到了很多答案。我想弄清楚为什么这个特定的代码会进入一个无限循环,而不是完全改变我的代码的方法(除非它根本上是错误的......)

主要是为什么会失败:

while abs(balance - fixedP*12)  >= epsilon:

该计划的目标是找到最小的每月支付一分钱,以便我们可以在一年内还清余额。

我下面的代码达到了数量(如果您在 while 循环中间插入 print (fixedP) 语句可以找到但它卡在无限循环中。我相信我的条件失败了,我不知道为什么。当余额变成“29157.09”,我的(fixedP * 12)检查也变成了29157.09,我以为while循环会停止。但是,它一直卡住。

balance = 320000
annualInterestRate = .2 
#above is given, below is my code

epsilon = 0.01  #precision check
balanceD = balance  #copy of balance
month = 0  #counter
monthlyRate = annualInterestRate/12  #given formula for problem

#bisection search parameters using given forumulas
low = balance / 12
high = (balance * (1+monthlyRate)**12)/12

fixedP = (low + high) / 2.0  #midpoint


while abs(balance - fixedP*12)  >= epsilon:
  unpaid = balance - fixedP
  newB = unpaid + monthlyRate*unpaid
  balance = newB
  month += 1

  if(month == 12 and balance > 0): #set new lower bound since original guess was too low
    low = fixedP
    fixedP = (high + low)/2
    balance = balanceD
    month = 0
  elif(month == 12 and balance < 0): #set new higher bound since original guess was too high
    high = fixedP
    fixedP = (low + high)/2
    balance = balanceD
    month = 0

print('Lowest Payment: ', round(fixedP, 2)) 

上面的代码达到了固定的每月金额,但它陷入了这个金额的无限循环。它永远不会退出 while 循环。你能帮我弄清楚为什么我的while循环条件失败了吗?

谢谢。

标签: pythonpython-3.xalgorithmbisection

解决方案


我在这里看到的问题更多是经济问题,而不是 Python 问题。

话虽如此,为了使您的代码正常工作,我们首先在 while 块之前添加以下行:

series_pw_factor = ((1+monthlyRate)**11 - 1) / (monthlyRate*(1+monthlyRate)**11)

然后我们可以修改你的条件如下:

while abs(balanceD - fixedP*series_pw_factor - fixedP)  >= epsilon:

现在解释一下经济学如何与这个问题联系起来:

您的 while 条件的问题在于它不考虑货币的时间价值(即利息)。如果您今天以 1000 美元贷款并每月支付 200 美元(每个月末),为期 5 个月,如果利息不为零,您仍将在 5 个月末欠贷款。

虽然问题中没有明确说明,但要获得答案“29157.09”,您必须假设第一笔付款是在第一个月的月初付款,最后一笔付款是在第十二个月的月初付款。

支付结构如下:

初始余额:320000 美元

t = 0 时的付款 1(1 月初):29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^0 = 29157.09

t = 1 时的付款 2(第 2 月初):29157.09,

t = 0 时的值是 29157.09 / (1+monthlyRate)^1 = 28679.10

在 t = 2(第 3 月初)支付 3:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^2 = 28208.96

在 t = 3(第 4 月初)支付 4:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^3 = 27746.51

在 t = 4(第 5 月初)支付 5:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^4 = 27291.65

在 t = 5(第 6 月初)支付 6:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^5 = 26844.25

在 t = 6(第 7 月初)支付 7:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^6 = 26404.18

在 t = 7(第 8 月初)支付 8:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^7 = 25971.32

在 t = 8(第 9 月初)支付 9:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^8 = 25545.56

t = 9 时支付 10(第 10 个月开始):29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^9 = 25126.78

在 t = 10(11 月初)支付 11:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^10 = 24714.87

在 t = 11(第 12 月初)支付 12:29157.09

t = 0 时的值是 29157.09 / (1+monthlyRate)^11 = 24309.71

当您将每次付款的 t = 0 处的值相加时,它将等于初始余额 $320000

这里的模式是我们本质上是在解决:

(1) initial_balance = payment*sum(1/(1+monthlyRate)^i) for i in [0,11]

或者

(2) initial_balance = (t = 0 时的付款) + payment*sum(1/(1+monthlyRate)^i) for i in [1,11]

在 (2) 中,术语“sum(1/(1+monthlyRate)^i) for i in [1,11]”被称为统一序列现值因子

这就是变量 series_pw_worth 因子的含义。

while 的条件确保满足(2)。

使用 (2),我们还可以看到单线解 O(1) 是:

fixedP = balance / (1 + ((1+annualInterestRate/12)**11 - 1) / (annualInterestRate/12*(1+annualInterestRate/12)**11))

推荐阅读