每次提交时,我都会在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)))
以下是测试结果:(我这里所有15个,所以你可能能够识别出我无法看到的模式。标记为&#34; ERROR&#34;的那些是我错误的模式)
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
答案 0 :(得分:3)
虽然函数是递归的(它自称), 它以毫无意义,无效的方式这样做。
考虑大于1时counter
的任何值会发生什么:
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!
当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)
这可能给出正确答案吗?不太可能。
考虑还款是如何运作的。 让我们举一个简单的例子,通过3个步骤来回报一些事情, 并考虑这种替代符号,因此写起来更简单:
T
支付今天支付的总金额 r
年利率的乘数,即4%的年利率,这个值将是1.04,因此我们可以通过{{1}获得需要支付的金额}。T * r
目标固定月付款我们本月支付x
后还需要多少钱来偿还?
x
也就是说,我们本月支付(T - x) * r
,剩余金额为x
,
根据描述,我们需要乘以年利率。
下个月,我们再次支付T - x
,所以还剩下的将是:
x
在第三个月,我们最后一次付款((T - x) * r - x) * r
。
练习的目标是找到x
,以便:
x
让我们重新组织这个等式来找到((T - x) * r - x) * r - x <= 0
:
x
在这个例子中,我们在3个月内偿还。 您可以通过添加一个月来了解此公式的变化:
((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
也就是说,给定T / (1 / r / r / r + 1 / r / r + 1 / r + 1) <= x
,添加一个月意味着T / m
。
现在看起来像我们可以使用的递归逻辑。
没有完全破坏你的运动,
这是解决方案的模板,您只需要找出T / (m / r + 1)
的正确值。祝你好运!
...
以下是一些验证您的解决方案的doctests。
如果您的程序位于名为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, ...)
的文件中,
您可以使用calc.py
运行doctests。
它将打印失败的测试用例的摘要,如果有的话,
或者如果一切都好的话,它什么都不打印。
python -mdoctest calc.py
答案 1 :(得分:2)
一个问题是:
假设利息每月复利
但你计算:
totalLoan = balance + (balance*annualInterestRate)
您不能以这种方式计算totalLoan。您应该考虑compound interest,并计算每个月的未付余额。
这是一个例子。请注意,您的递归可以用简单的循环替换:
def balance_after_a_year(balance, monthly_payment, annual_interest_rate):
monthly_interest_rate = annual_interest_rate / 12.0
for month in range(12):
balance = (balance - monthly_payment) * (1 + monthly_interest_rate)
return balance
print(balance_after_a_year(3834, 340, 0.15))
# 23.153402858591026
print(balance_after_a_year(3834, 350, 0.15))
# -107.05775649703746
您现在可以以天真的方式使用此功能。只需以10为步长从0
迭代到balance
,然后选择一年后余额为负数的第一个值:
def getFixedPayment(b,r):
return next(m for m in range(0, b, 10) if balance_after_a_year(b, m, r) <= 0)
print(getFixedPayment(3834, 0.15))
# 350
此方法已通过@janos提供的doctest验证。
有更有效的方法,但这个方法简单明了。
您可以使用monthly payment formula直接计算付款:
def getFixedPayment(b,r):
m = r / 12.0
return m * b / (1 - (1 + m)**-12)
print(getFixedPayment(3834, 0.15))
# 346.05036953133276
不需要任何循环!