Python:使用递归查找10的倍数的最低固定月付款

Deb*_*255 5 python recursion

我每次提交时都会在edX.org上的Python课程中得到11或12个正确,但是在讨论中没有得到任何人的帮助,因为没有人可以在那里发布任何代码(没有真正有用)并且没有似乎是任何可用的支持人员从课程中说话,我会付钱,所以我在这里发帖.我正要付钱给某人来指导我,但现在没有人可以使用,而且我有一些压力要在12月之前为我的工作完成这门课程.

这是作业:

现在编写一个程序,计算所需的最低固定月付款,以便在12个月内偿还信用卡余额.按固定的每月付款,我们指的是每个月不变的单个数字,而是每月支付的固定金额.

在这个问题上,我们不会处理最低月付款率.

以下变量包含如下所述的值:

余额 - 信用卡上的未结余额

annualInterestRate - 年度利率小数

该计划应打印出一行:每月最低付款,以偿还1年内的所有债务,例如:

最低付款:180
假设利息按月末的余额(在该月的付款之后)按月复利.每月付款必须是10美元的倍数,并且所有月份都相同.请注意,使用此付款方案可能会使余额变为负数,这是可以的.所需数学的摘要如下:

每月利率=(年利率)/ 12.0
每月未付余额=(以前的余额) - (每月最低固定付款额)每月
更新余额=(每月未付余额)+(每月利率x每月未付余额)

这是我的代码:

#! /usr/bin/python3.6

from math import ceil

def roundup(x):
    return int(ceil(x / 10.0) * 10)

def getFixedPayment(balance,annualInterestRate,counter=12):

    totalLoan = balance + (balance*annualInterestRate)
    monthlyPayment = roundup(totalLoan/12.0)
    newBalance = totalLoan - monthlyPayment
    if counter < 12:
        newPayment = newBalance / counter + 1
    else:
        newPayment = newBalance / counter

    if counter == 1:
        return roundup(newPayment/12)
    else:
        return getFixedPayment(balance,annualInterestRate,counter-1)


#balance = 3329
#annualInterestRate = 0.2
print('Lowest Payment: ' + str(getFixedPayment(balance,annualInterestRate)))
Run Code Online (Sandbox Code Playgroud)

以下是测试结果:(我这里有15个,所以你可能能够识别出我看不到的模式.标记为"ERROR"的是我得到的错误)

Test Case 1
balance = 3329; annualInterestRate = 0.2
Output:
Lowest Payment: 310

Test Case 2
balance = 4773; annualInterestRate = 0.2
Output:
Lowest Payment: 440

Test Case 3
balance = 3926; annualInterestRate = 0.2
Output:
Lowest Payment: 360

Randomized Test Case 1
balance = 265; annualInterestRate = 0.18
Output:
Lowest Payment: 30

Randomized Test Case 2
balance = 263; annualInterestRate = 0.18
Output:
Lowest Payment: 30

Randomized Test Case 3
balance = 317; annualInterestRate = 0.25
Output:
Lowest Payment: 30

Randomized Test Case 4
balance = 720; annualInterestRate = 0.2
Output:
Lowest Payment: 70

Randomized Test Case 5
balance = 4284; annualInterestRate = 0.2
Output:
Lowest Payment: 400

Randomized Test Case 6
balance = 3834; annualInterestRate = 0.15
Your output:
Lowest Payment: 340


*** ERROR: Expected Lowest Payment: 350

, but got Lowest Payment: 340

 ***
Correct output:
Lowest Payment: 350

Randomized Test Case 7
balance = 3045; annualInterestRate = 0.18
Output:
Lowest Payment: 280

Randomized Test Case 8
balance = 4461; annualInterestRate = 0.2
Output:
Lowest Payment: 410

Randomized Test Case 9
balance = 4657; annualInterestRate = 0.04
Your output:
Lowest Payment: 370


*** ERROR: Expected Lowest Payment: 400

, but got Lowest Payment: 370

 ***
Correct output:
Lowest Payment: 400

Randomized Test Case 10
balance = 3395; annualInterestRate = 0.2
Your output:
Lowest Payment: 320


*** ERROR: Expected Lowest Payment: 310

, but got Lowest Payment: 320

 ***
Correct output:
Lowest Payment: 310

Randomized Test Case 11
balance = 4045; annualInterestRate = 0.15
Your output:
Lowest Payment: 360


*** ERROR: Expected Lowest Payment: 370

, but got Lowest Payment: 360

 ***
Correct output:
Lowest Payment: 370

Randomized Test Case 12
balance = 3963; annualInterestRate = 0.18
Output:
Lowest Payment: 360
Run Code Online (Sandbox Code Playgroud)

Sto*_*ica 3

尽管该函数是递归的(它调用自身),但它是以一种毫无意义、无效的方式实现的。

考虑当 的任何值counter大于 1 时会发生什么:

def getFixedPayment(balance, annualInterestRate, counter=12):
    totalLoan = balance + (balance*annualInterestRate)
    monthlyPayment = roundup(totalLoan/12.0)
    newBalance = totalLoan - monthlyPayment

    if counter < 12:
        newPayment = newBalance / counter + 1
    else:
        newPayment = newBalance / counter

    if counter == 1:
        return roundup(newPayment/12)
    else:
        return getFixedPayment(balance,annualInterestRate,counter-1)
        #                                                 ^^^^^^^^^
        #                                                 the only change!
Run Code Online (Sandbox Code Playgroud)

当 时counter > 1,函数“进行一些计算”,但这并不重要,因为最终它只是用 调用自身counter - 1。因此,对于 的起始值counter = 12,该函数将毫无意义地重复调用自身 11 次。因此它简化为:

def getFixedPayment(balance, annualInterestRate):
    totalLoan = balance + (balance*annualInterestRate)
    monthlyPayment = roundup(totalLoan/12.0)
    newBalance = totalLoan - monthlyPayment

    newPayment = newBalance / counter + 1

    return roundup(newPayment/12)
Run Code Online (Sandbox Code Playgroud)

这可能给出正确答案吗?不见得。

考虑还款的方式。让我们举一个更简单的例子,分 3 步偿还某物,并考虑这种替代表示法,这样写起来更简单:

  • 我们来算一下今天T​​要支付的总金额
  • 我们称之为r年利率的乘数,即年利率为4%,这个值为1.04,这样我们就可以得到需要支付的金额T * r
  • 我们将x目标称为每月固定付款

这个月还款后x,还剩下多少钱?

(T - x) * r
Run Code Online (Sandbox Code Playgroud)

也就是说,我们x这个月还款,剩余金额为T - x,根据描述我们需要乘以年利率。

下个月,我们x再次付款,所以还剩下:

((T - x) * r - x) * r
Run Code Online (Sandbox Code Playgroud)

在第三个月,我们支付了最后一次付款x

练习的目标是找到x

((T - x) * r - x) * r - x <= 0
Run Code Online (Sandbox Code Playgroud)

让我们重新组织这个方程来找出 的值x

((T - x) * r - x) * r <= x

(T - x) * r - x <= x / r

(T - x) * r <= x / r + x

T - x <= x / r / r + x / r

T <= x / r / r + x / r + x

T <= x * (1 / r / r + 1 / r + 1)

T / (1 / r / r + 1 / r + 1) <= x
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我们在 3 个月内还款。您可以通过添加一个月来查看此公式的变化:

T / (1 / r / r / r + 1 / r / r + 1 / r + 1) <= x
Run Code Online (Sandbox Code Playgroud)

也就是说,给定T / m,添加一个月意味着T / (m / r + 1)

现在看起来我们可以使用递归逻辑。

在不完全破坏您的练习的情况下,这里有一个解决方案模板,您只需计算出 的正确值即可...。祝你好运!

def getFixedPayment(balance, annual_interest_rate, counter=12, interest=...):

    if counter == 1:
        return roundup(balance / interest)

    monthly_interest_rate = annual_interest_rate / 12
    r = 1 + monthly_interest_rate

    return getFixedPayment(balance, annual_interest_rate, counter - 1, ...)
Run Code Online (Sandbox Code Playgroud)

这里有一些文档测试来验证您的解决方案。如果您的程序位于名为 的文件中calc.py,则可以使用 运行文档测试python -mdoctest calc.py。它将打印失败测试用例的摘要(如果有),或者如果一切正常则不会打印任何内容。

def getFixedPayment(balance, annual_interest_rate, counter=12, interest=...):
    """
    >>> getFixedPayment(3329, 0.2)
    310

    >>> getFixedPayment(4773, 0.2)
    440

    >>> getFixedPayment(3926, 0.2)
    360

    >>> getFixedPayment(265, 0.18)
    30

    >>> getFixedPayment(263, 0.18)
    30

    >>> getFixedPayment(317, 0.25)
    30

    >>> getFixedPayment(720, 0.2)
    70

    >>> getFixedPayment(4284, 0.2)
    400

    >>> getFixedPayment(3834, 0.15)
    350

    >>> getFixedPayment(3045, 0.18)
    280

    >>> getFixedPayment(4461, 0.2)
    410

    >>> getFixedPayment(4657, 0.04)
    400

    >>> getFixedPayment(3395, 0.2)
    310

    >>> getFixedPayment(4045, 0.15)
    370

    >>> getFixedPayment(3963, 0.18)
    360

    """

    if counter == 1:
        return roundup(balance / interest)

    monthly_interest_rate = annual_interest_rate / 12
    r = 1 + monthly_interest_rate

    return getFixedPayment(balance, annual_interest_rate, counter - 1, ...)
Run Code Online (Sandbox Code Playgroud)