简体   繁体   English

如何在循环内(但仅在第一次迭代之后)更改条件?

[英]How do I change a condition within a loop, but only after the first iteration?

I'm creating a simple model which calculates the minimum fixed monthly payment required to pay off a credit card balance within 12 months. 我正在创建一个简单的模型,该模型计算在12个月内还清信用卡余额所需的最低每月固定费用。

My code: 我的代码:

balance = 3329             # starting balance
annualInterestRate = 0.2   # yearly interest rate
minFixedPayment = 0        # initiate a minimum monthly payment of 0

while balance > 0:
    minFixedPayment = minFixedPayment + 10
    for i in range(1,13,1):
        unpaidBalance = balance - minFixedPayment
        balance = unpaidBalance + ((annualInterestRate/12) * unpaidBalance)
        i=i+1
print(round(minFixedPayment,2))

I added the "minFixedPayment" increment BEORE the for loop so that it keeps incrementing until it finds a value where balance is <= 0 at the end of month 12. I know this is wrong since it will compute the first iteration with minFixedPayment = 10, not 0. Is there a better way to arrange this? 我在for循环之前添加了“ minFixedPayment”增量,以便它一直递增,直到在第12个月末找到余额<= 0的值为止。我知道这是错误的,因为它将使用minFixedPayment = 10计算第一次迭代,而不是0。是否有更好的方法来安排呢?

I've tried adding the 我尝试添加

minFixedPayment = minFixedPayment + 10

statement to the end of the loop, like this: 语句到循环结束,如下所示:

while balance > 0:
    for i in range(1,13,1):
        unpaidBalance = balance - minFixedPayment
        balance = unpaidBalance + ((annualInterestRate/12) * unpaidBalance)
        i=i+1
    minFixedPayment = minFixedPayment + 10 # moved this to after the loop
print(round(minFixedPayment,2))

but that makes the while loop run forever (why?). 但这会使while循环永远运行(为什么?)。

Is there a better way to approach this? 有没有更好的方法来解决这个问题? Thank you for your time. 感谢您的时间。

Some issues: 一些问题:

  • As your intention is to try with different payment amounts, you should reset the balance to its original value with each attempt. 由于您打算尝试使用不同的付款金额,因此每次尝试都应将余额重置为原始值。 Without that, you can get into an infinite loop with an ever increasing balance. 没有这些,您将陷入不断增加的平衡的无限循环。 In order to be able to reset the balance, you'll need to store it in a second name as well. 为了能够重置余额,您还需要将其存储为第二名称。
  • You should not increase i with i=i+1 . 您不应该以i=i+1增加i That is already taken care of with the for loop. for循环已经解决了这一for

Here is the suggested code: 这是建议的代码:

loan = balance = 3329      # starting balance, use two names so you can restart
annualInterestRate = 0.2   # yearly interest rate
minFixedPayment = -10      # initiate a minimum monthly payment

monthlyInterestRate = annualInterestRate/12 # avoid doing this repeatedly

while balance > 0:
    minFixedPayment = minFixedPayment + 10
    balance = loan # start from scratch
    for i in range(1,13):
        unpaidBalance = balance - minFixedPayment
        balance = unpaidBalance + monthlyInterestRate * unpaidBalance

print(round(minFixedPayment,2))

For your interest, here is a more sophisticated solver: 为了您的兴趣,这里有一个更复杂的求解器:

from functools import partial
from math import ceil

def diff(fn, x, h=0.001):
    """
    Numerically differentiate fn at x
    """
    return (fn(x + h) - fn(x)) / h

def newton_solver(fn, target_y, initial_x, max_reps=100, max_err=0.01):
    """
    Find a value for x such that fn(x) == target_y (+/- max_err)
    """
    x = initial_x
    for _ in range(max_reps):
        err = fn(x) - target_y
        if abs(err) <= max_err:
            # found a good enough solution
            return x
        else:
            # first-order correction to reduce error
            x -= err / diff(fn, x)
    raise ValueError("solver failed to converge")

def final_balance(fixed_payment, initial_balance, period_rate, num_periods):
    """
    Calculate the final balance on a fixed payment plan
    """
    balance = initial_balance
    for _ in range(num_periods):
        balance = (balance - fixed_payment) * (1. + period_rate)
    return balance

def round_up_to_next_cent(amt):
    return ceil(amt * 100.) / 100.

def main():
    initial_balance = 3329.
    annual_interest = 0.2

    # bind arguments to create a single-argument function to pass to newton_solver
    my_final_balance = partial(final_balance, initial_balance = initial_balance, period_rate = annual_interest / 12, num_periods = 12)

    # initial guess - in total you will pay about half a year's interest
    monthly_payment_guess = initial_balance * (1. + annual_interest * 0.5) / 12

    # solve to find accurate value
    monthly_payment = newton_solver(my_final_balance, 0., monthly_payment_guess)
    monthly_payment = round_up_to_next_cent(monthly_payment)

    # and report the result
    print("A fixed monthly payment of ${:0.2f} results in a final balance of ${:0.2f}".format(monthly_payment, my_final_balance(monthly_payment)))

if __name__ == "__main__":
    main()

which produces 产生

A fixed monthly payment of $303.33 results in a final balance of $-0.07

add a flag variable to control if balance is changed. 添加一个标志变量来控制是否更改余额。 Another way could be to check if balance is changed. 另一种方法是检查余额是否已更改。 ( if balance != original_balance: ... ) eg if balance != original_balance: ... )例如

balance = 3329             # starting balance
annualInterestRate = 0.2   # yearly interest rate
minFixedPayment = 0        # initiate a minimum monthly payment of 0
change_flag = 0
while balance > 0:
    if change_flag: minFixedPayment = minFixedPayment + 10
    change_flag = 1
    for i in range(1,13,1):
        unpaidBalance = balance - minFixedPayment
        balance = unpaidBalance + ((annualInterestRate/12) * unpaidBalance)
        i=i+1
print(round(minFixedPayment,2))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM