【问题标题】:How do I change a condition within a loop, but only after the first iteration?如何在循环中更改条件,但仅在第一次迭代之后?
【发布时间】:2017-06-17 08:27:01
【问题描述】:

我正在创建一个简单的模型,用于计算在 12 个月内还清信用卡余额所需的最低每月固定付款额。

我的代码:

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))

我在 for 循环之前添加了“minFixedPayment”增量,以便它不断增加,直到在第 12 个月末找到余额

我已经尝试添加

minFixedPayment = minFixedPayment + 10

声明到循环结束,像这样:

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))

但这会使 while 循环永远运行(为什么?)。

有没有更好的方法来解决这个问题? 感谢您的宝贵时间。

【问题讨论】:

  • 为什么不以minFixedPayment = -10 开头并打印/返回max(0, round(minFixedPayment,2))
  • 另外,您正在计算 3329 的 20% 利息贷款并支付 10 美元,很可能您永远不会还清。
  • 一般建议:放弃 while 循环并设置运行时或迭代的上限。接下来,为了保持稳健,您可能需要检查余额何时降至一美分以下,而不是像@ChihebNexus 指出的那样低于零。
  • @trincot 聪明!但仍然使while循环永远运行:(
  • @RYS 只是采样值,为一个类做这个:) 我会尝试在循环上设置一个不同的上限,谢谢!

标签: python loops for-loop while-loop


【解决方案1】:

一些问题:

  • 由于您打算尝试使用不同的付款金额,您应该在每次尝试时将余额重置为其原始值。没有它,你可能会进入一个无限循环,平衡不断增加。为了能够重置余额,您还需要将其存储在另一个名称中。
  • 您不应将i 增加到i=i+1for 循环已经解决了这个问题。

这是建议的代码:

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))

【讨论】:

  • 成功了!!! :))) 谢谢。我认为关键是在每次循环后重新启动余额值,并将初始 minFixPayment 设置为 -10。聪明的!也谢谢你的清理,我已经盯着它看了一段时间,忘记了那里的一些冗余代码。
【解决方案2】:

为了您的兴趣,这里有一个更复杂的求解器:

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()

产生

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

【讨论】:

    【解决方案3】:

    添加一个标志变量来控制平衡是否改变。另一种方法可能是检查余额是否发生变化。 (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))
    

    【讨论】:

    • 尝试使用较小的余额,例如1000
    猜你喜欢
    • 1970-01-01
    • 2016-06-19
    • 2015-10-20
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多