使用近似解和二等分搜索

时间:2018-07-12 01:54:05

标签: python python-3.x algorithm bisection

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

主要,为什么会失败:

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循环条件失败?

谢谢。

2 个答案:

答案 0 :(得分:1)

我在这里看到的问题更多是经济问题,而不是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”,您必须假定第一笔付款是在第一个月初支付的,最后一笔付款是在第12个月初支付的

付款结构如下:

初始余额:$ 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 =付款*总和(1 /(1(monthlyRate)^ i),用于[0,11]中的i

(2)初始余额=(在t = 0时支付)+支付*总和(1 /(1 + monthlyRate)^ i)在[1,11]中为i

在(2)中,[1,11]中i的项'sum(1 /(1 + monthlyRate)^ i)'为 被称为统一序列现值因子

这就是变量series_pw_worth系数的含义。

该条件确保满足(2)。

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

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

答案 1 :(得分:0)

您的逻辑以及其他所有内容都是正确的。但是您的while函数逻辑有些不正确,abs(balance-fixedP * 12)> = epsilon时,请勿进行比较。应该是:

while balance >= epsilon:

或者:

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

此外,您需要在以后的比较中将余额与epsilon而不是0进行比较。

因为余额应该是从您剩余的月份中扣除的值,所以您不应在此处使用12。

还有您的代码

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 balance >= epsilon:
    unpaid = balance - fixedP
    newB = unpaid + monthlyRate*unpaid
    balance = newB
    month += 1
    if(month == 12 and balance > epsilon): #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 < -epsilon): #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)) 

或者,当您获得所需的值时,可以使用break函数退出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 True:
    unpaid = balance - fixedP
    newB = unpaid + monthlyRate*unpaid
    balance = newB
    month += 1
    if(month == 12 and balance > epsilon): #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 < -epsilon): #set new higher bound since original guess was too high
        high = fixedP
        fixedP = (low + high)/2
        balance = balanceD
        month = 0
    else:
        break

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

随时发布您不清楚的任何内容。谢谢。