8

以下を使用して、ローンを完済するための毎月の最低支払い額を計算しようとしています。

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

みんな助けてくれてありがとう!

4

8 に答える 8

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)
于 2013-12-01T12:09:27.270 に答える
3

このようなバグを見つけるには、印刷物を追加するのが良い方法です。たとえば、コードに次のように追加しました。

print(balance, lo, hi, guess)

次に、何が起こっているかを確認すると、何が起こっているのかを理解できます。それが判明したとして:

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

低すぎる上限を計算します。おそらくあなたは意味しました:

hi = (balance*(1+monthlyInterestRate*12))/12
于 2013-03-18T19:38:18.010 に答える
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」を「high」と「low」に変更しました。切り捨てられた変数名は読みにくくなるため、変数名を切り捨てない方がよいでしょう。

さまざまな変数の値を示すデバッグ ステートメントを追加しました。

上記を実行した結果は次のとおりです。

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 
于 2013-03-18T19:54:12.410 に答える
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))
于 2016-11-13T00:35:08.800 に答える
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))
于 2017-06-18T14:41:19.903 に答える