2013-03-18 45 views
8

我试图计算每月最低支付使用还清贷款下面分搜索最低月付:计算使用python的

balance = 999999 
annualInterestRate = .18 
monthlyInterestRate = annualInterestRate/12 

balanceCOPY = balance 

#Bisection search parameters 

lo = balance/12 
hi = (balance*(1+monthlyInterestRate**12))/12 
epsilon = .01 

guess = (lo + hi)/2 

while True: 
    for month in range(1,13): 
     balance = balance - guess 
     balance = balance + (monthlyInterestRate*balance) 

    if balance > 0 and balance > epsilon: 
     lo = guess 
     balance = balanceCOPY 
    elif balance < 0 and balance < -epsilon: 
     hi = guess 
     balance = balanceCOPY 
    else: 
     print('Lowest payment: ',str(round(guess,2))) 
     break 

    guess = (lo + hi)/2 

但是,我似乎被卡在某种无限循环,其中guess变量未被更新。我怎样才能摆脱无限循环并让我的guess变量更新?

问题出在我的数学上。我的意思是说

hi = (balance*(1+monthlyInterestRate)**12)/12 

谢谢所有帮助大家!

+0

什么是你的问题? (并且,“[SSCCE] +1(http://SSCCE.org)”)。 – 2013-03-18 19:13:45

+0

您是否尝试过在循环的每次迭代期间打印出所有变量,并查看其中一个是否未更新?你也从哪里得到这个算法? – placeybordeaux 2013-03-18 19:31:53

+0

你知道有这样的公式,对吧? http://en.wikipedia.org/wiki/Compound_interest#Simplified_calculation – 2013-03-18 19:32:42

回答

3

要找出这样的错误,一个很好的办法就是添加一些打印,例如,添加以下到您的代码:

print(balance, lo, hi, guess) 

然后看看会发生什么,你可以找出什么是继续。事实证明:

hi = (balance*(1+monthlyInterestRate**12))/12 

计算的上限过低。也许你的意思是:

hi = (balance*(1+monthlyInterestRate*12))/12 
+1

感谢您指出这部分出我的程序。我无法相信我总是会错过一些愚蠢的事情。我的意思是hi =(balance *(1+ monthlyInterestRate)** 12)/ 12 – 2013-03-18 20:05:24

3

我改变你的代码如下:

balance = 999999 
annualInterestRate = .18 
monthlyInterestRate = annualInterestRate/12 

balanceCOPY = balance 

#Bisection search parameters 

low = balance/12 
high = (balance * (1 + monthlyInterestRate ** 12))/12 
epsilon = .01 

print "starting high and low guesses" 
print "high: %s" % high 
print "Low: %s" % low 
print "\n" 

guess = (low + high)/2 

for i in range(5): 

    print "Type of balance: %s" % type(balance) 
    print "Balance is: %s" % balance 
    print "Low: %s" % low 
    print "High: %s" % high 
    print "Guess: %s" % guess 

    print "monthly interest %s" % (monthlyInterestRate * balance) 

    for month in range(1, 13): 
     balance -= guess 
     balance += monthlyInterestRate * balance 

    print "balance after %s" % balance 

    if balance > 0 and balance > epsilon: 
     print "Change low" 
     low = guess 
     balance = balanceCOPY 
    elif balance < 0 and balance > -epsilon: 
     high = guess 
     balance = balanceCOPY 
    else: 
     print('Lowest payment: ', str(round(guess, 2))) 
     break 

    guess = (low + high)/2 

    print "\n" 

有两点要注意: 我改 “HI” 和 “LO” 到 “高” 和 “低”。最好不要截断变量名称,因为截断的变量名称的可读性较差。

我添加了显示各种变量值的调试语句。

这里是运行上面的结果:

starting high and low guesses 
high: 83333.25 
Low: 83333 


Type of balance: <type 'int'> 
Balance is: 999999 
Low: 83333 
High: 83333.25 
Guess: 83333.125 
monthly interest 14999.985 
balance after 92550.599997 
Change low 


Type of balance: <type 'int'> 
Balance is: 999999 
Low: 83333.125 
High: 83333.25 
Guess: 83333.1875 
monthly interest 14999.985 
balance after 92549.7726951 
Change low 


Type of balance: <type 'int'> 
Balance is: 999999 
Low: 83333.1875 
High: 83333.25 
Guess: 83333.21875 
monthly interest 14999.985 
balance after 92549.3590442 
Change low 


Type of balance: <type 'int'> 
Balance is: 999999 
Low: 83333.21875 
High: 83333.25 
Guess: 83333.234375 
monthly interest 14999.985 
balance after 92549.1522187 
Change low 


Type of balance: <type 'int'> 
Balance is: 999999 
Low: 83333.234375 
High: 83333.25 
Guess: 83333.2421875 
monthly interest 14999.985 
balance after 92549.048806 
Change low 

从这里就可以看出,你的低价值收敛到您的高价值。换句话说,你的初始高价值不够高。一旦它们具有相同的价值,循环将永远不会改变任何东西,并将永远持续下去。

我觉得这行:

elif balance < 0 and balance < -epsilon: 

应改为:

elif balance < 0 and balance > -epsilon: 

,因为我想你想也0-epsilon之间的平衡,而不是小于-epsilon

,如@WinstonEwert注意:

hi = (balance*(1+monthlyInterestRate**12))/12 

应该

hi = (balance*(1+monthlyInterestRate)**12)/12 
+0

确保你修复了'elif balance <0和balance <-epsilon:'。现在你正在检查余额是小于0还是小于-0.01。请注意,-100000000000符合该条件。 – mydogisbox 2013-03-18 20:57:04

5

我觉得这个解决方案应该工作,

balance = 999999 
annualInterestRate = 0.18 

monthlyInterestRate = annualInterestRate/12 
lowerBound = balance/12 
upperBound = (balance * (1 + annualInterestRate/12) ** 12)/12 
originalBalance = balance 
lowestBalance = 0.01 # Error margin e.g. $0.01 

# Keep testing new payment values until the balance is +/- lowestBalance 
while abs(balance) > lowestBalance: 
    # Reset the value of balance to its original value 
    balance = originalBalance 
    # Calculate a new monthly payment value from the bounds 
    payment = (upperBound - lowerBound)/2 + lowerBound 

    # Test if this payment value is sufficient to pay off the entire balance in 12 months 
    for month in range(12): 
     balance -= payment 
     balance *= 1 + monthlyInterestRate 

    # Reset bounds based on the final value of balance 
    if balance > 0: 
     # If the balance is too big, need higher payment so we increase the lower bound 
     lowerBound = payment 
    else: 
     # If the balance is too small, we need a lower payment, so we decrease the upper bound 
     upperBound = payment 

# When the while loop terminates, we know we have our answer! 
print "Lowest Payment:", round(payment, 2) 
4

首先,如果你正在做MITX锻炼,并完成了先前的测试(只是为了增加在猜测10)你需要一小步才能得到它。只需要对条件进行一些调整并查看年度结果。

关于平分搜索我会尽力澄清概念。你将永远有两个极端,最小和最大。并且总会在四肢中间开始猜测。

第一次猜测后,您需要根据年度结果调整四肢。如果一年后支付了最低限度的饮料,女孩,节目和其他东西,你没有支付总余额,你肯定需要提高最低限度。否则,例如,如果您在第10个月支付了总余额,则您需要多喝水,并明年见到新女孩!只是开玩笑...你需要减少最低限度。这是你需要支付难


在运动中完成一年后做检查,我们有:

  • 平衡和annualInterestRate =给予(我们并不需要关心)
  • 最小值(下限)=平衡/ 12
  • 最大值(上限)=(余额×(1 +每月利率)** 12)/ 12.0

的第一个猜测将是(最小+最大值)/ 2我叫guessMinimum这样:

guessMinimum = (minimum + maximum)/2 

所以你开始使用第一猜测(guessMinimum)。一年后你会检查剩下的。 如果剩余是负数,则表示您已付出太多。你需要减少每月付款。在其他方面,如果一个月后余下的是正数(例如,超过您的精度(例如0.10)),您需要减少每月付款,好吗?!

试图设计思维.....

+------------------------------------------------+ 
| /\     /\     /\ | 
| \/------------------\/-------------------\/ | 
|MINIMUM    guess    MAXIMUM| 
|      Minimum     | 
+------------------------------------------------+ 

如果一年后,在 “保持” 是(例如)阴性。意思是'guessMinimum'很重要!你需要...不是你,程序!程序需要调整它,降低最小值......

+---------------------------------------------------+ 
|      Got negative 'remain'  | 
|     ++        | 
| /\    || /\     /\ | 
| \/-------------||---\/-------------------\/ | 
| MINIMUM   || guess    MAXIMUM | 
|     ++ Minimum-,     | 
|        ',     | 
|         `.    | 
|         `.,    | 
|          ',   | 
|          ',   | 
|           `.  | 
|           `  | 
| /\     /\     /\ | 
| \/------------------\/-------------------\/ | 
| MINIMUM    guess    MAXIMUM | 
+---------------------------------------------------+ 

对不起大家。我试图插入一个图像,但作为一个新成员。我不能。至少需要10个声望....帮助我!!!!太多的工作使用字符!

和代码需要为此努力工作调整了最低,直到“保持”是可以接受的(你的精度,或ε,或任何字母或变量或...好吧内。:)

经了解概念和图纸..让我们检查代码。

balance = 999999; 
annualInterestRate = 0.18 

monthlyInterestRate = annualInterestRate/12 

minimum = balance/12 
maximum = (balance * (1 + monthlyInterestRate)**12)/12.0 

guessMinimum = (minimum + maximum)/2 

remain = balance #if you payed nothin, the remain is the balance!!!! 

precision = 0.10 #you choose.... 

while (remain >= precision): 

    guessMinimum = (minimum + maximum)/2 


    for i in range (1,13): 

     newBalance = remain - guessMinimum 
     monthInterest = annualInterestRate/12*newBalance 
     remain = newBalance+monthInterest 

    # after one month, the CODE need to check about the remain 

    if (remain < 0): #paying too much.... need to decrease the value 

     maximum = guessMinimum  #remember my beautiful draw above!! 
     remain = balance # reset the remain to start again!! 

    elif (remain > precision): #paying less .... need to increase the value 
     minimum = guessMinimum 
     remain = balance # reset the remain to start again!! 

print "Lowest Payment: %.2f" %(guessMinimum) 

就是这样。

1

这是我想出的作品。我通常会为这些类型的事物编写函数,以便可以重用,即使我不需要,因为它让我养成了这样的习惯,并且给了我一些额外的练习。

balance = 320000 
annualInterestRate=0.2 
monthlyIntRate= annualInterestRate/12.0 
getpayment=True 
ranonce=False 
MoMin = balance/12 
MoMax = (balance*(1+monthlyIntRate)**12)/12.0 
MoPayment = (MoMin+MoMax)/2 
NewBal=0 

#Create a function to run 12 months of payments, and then create a loop to re-run the function if the Ending Balance is not close enough to 0. 
def CCPayment(balance, monthlyIntRate, MoPay): 
    global NewBal  
    Month = 1 #Month begins at 1 

    while Month <= 12: 
      balance = (balance - MoPay) 
      balance = balance + (monthlyIntRate * balance) 
      NewBal=balance #sets the var NewBal to be used globally 
      Month += 1 
    if (balance < .02) and (balance > -0.02) : #cannot evaluate to '0' as you are evaluating a float and it will 'inf loop'. Must evaluate it to a number 'close enough' 
     return MoPayment 
    else: 
     return False 

while getpayment==True: 
    if CCPayment(balance, monthlyIntRate, MoPayment): 
     getpayment=False 
     print "Lowest Payment: ", round(CCPayment(balance, monthlyIntRate, MoPayment),2) 
    else: 
     if NewBal < 0.01: #paid too much! Lower the max payment and rerun function 
      if ranonce == True: #Bool check to avoid resetting the Min/Max values before running it once 
       MoMax=MoPayment #sets the Max payment to the current monthly payment 
       MoPayment=(MoMin+MoMax)/2 #sets the Monthly payment to average the Min/Max payments 
      ranonce = True 
      CCPayment(balance, monthlyIntRate, MoPayment) 

     elif NewBal > 0.01: #didn't pay enough! Raise min payment and rerun function 
      if ranonce == True: #Bool check to avoid resetting the Min/Max values before running it once 
        MoMin=MoPayment #sets the Min payment to the current monthly payment 
        MoPayment=(MoMin+MoMax)/2 #sets the Monthly payment to average the Min/Max payments 
      ranonce = True 
      CCPayment(balance, monthlyIntRate, MoPayment) 
0
monthlyInterestRate = annualInterestRate/12 
monthlyPaymentLowerBound = balance/12 
monthlyPaymentUpperBound = (balance * (1 + monthlyInterestRate)**12)/12 
epsilon = 0.01 
while True: 
    unpaidBalance = balance 
    minimumFixedMonthlyPayment = (monthlyPaymentLowerBound + monthlyPaymentUpperBound)/2 

    for i in range(12): 
     if i == 0: 
      unpaidBalance = balance - minimumFixedMonthlyPayment 
     else: 
      updatedBalance = unpaidBalance + (monthlyInterestRate * unpaidBalance) 
      unpaidBalance = updatedBalance - minimumFixedMonthlyPayment 

    if unpaidBalance > 0 and abs(unpaidBalance) > epsilon: 
     monthlyPaymentLowerBound = minimumFixedMonthlyPayment 
     minimumFixedMonthlyPayment = (minimumFixedMonthlyPayment + monthlyPaymentUpperBound)/2 
     continue 
    elif unpaidBalance < 0 and abs(unpaidBalance) > epsilon: 
     monthlyPaymentUpperBound = minimumFixedMonthlyPayment 
     minimumFixedMonthlyPayment = (monthlyPaymentLowerBound + minimumFixedMonthlyPayment)/2 
    else: 
     break 
print(round(minimumFixedMonthlyPayment, 2)) 
0

Python 3的答案:

balance = 999999 
annualInterestRate = .18 

monthlyInterestRate = annualInterestRate/12.0 
lowBound = balance/12 
hiBound = (balance*(1+monthlyInterestRate)**12)/12.0 
epsilon = 0.01 

newBalance = balance 
while abs(newBalance) > epsilon: 
    minPay = (lowBound + hiBound)/2 
    newBalance = balance 
    for month in range(12): 
     monthlyUnpaid = newBalance - minPay 
     newBalance = monthlyUnpaid + (monthlyInterestRate * monthlyUnpaid) 
    if newBalance > epsilon: 
     lowBound = minPay 
    elif newBalance < epsilon: 
     hiBound = minPay 
print ("Lowest Payment: ", round(minPay, 2))