简体   繁体   English

在 Python 中实现差分(非差分)方程

[英]Implementing difference (NOT differential) equations in Python

I'm trying to implement a difference equation in Python.我正在尝试在 Python 中实现一个差分方程。 These take the form y n+1 = a * y n + b, given y 0 where y 0 is initial value and it iterates -- meaning这些采用 y n+1 = a * y n + b 的形式,给定 y 0 ,其中 y 0是初始值并且它进行迭代——意思是

y 1 = a * y 0 + b, y 1 = a * y 0 + b,
y 2 = a * y 1 + b, y 2 = a * y 1 + b,
... ...

An example problem (from my calculus class) would be thus: Say you take out a loan of $60,000 and plan on paying $700 a month back at an interest rate of 1.2%.一个示例问题(来自我的微积分课)是这样的:假设您贷款 60,000 美元,并计划以 1.2% 的利率每月偿还 700 美元。 How much would be left after 5 years? 5年后还剩多少? This would be set up as y n+1 = 1.1 * y n - 700, y 0 = 60,000这将被设置为 y n+1 = 1.1 * y n - 700, y 0 = 60,000

I understand recursion in Python in the sense that you can say, for example,我理解 Python 中的递归,你可以说,例如,

i = 0
while i < 20:
    i = i+1

but I'm unsure how to approach it when the next iteration requires a value from the previous.但是当下一次迭代需要前一次的值时,我不确定如何处理它。

def calc1():
    S=60000
    x=0.012
    y=5*12
    Pmt=700
    r=1+(x/12)
    Ln = S
    for k in range(1, y+1):
         Ln=(Ln*r)-Pmt
    print (Ln)

Result: $20444.98结果:20444.98 美元

Or using algebra with definition of sum of geometric progression或者使用代数定义几何级数和

Ln= S * r y - Pmt * ((1-r y ) / (1-r)) = $20444.98 Ln= S * r y - Pmt * ((1-r y ) / (1-r)) = $20444.98

Sorry Stackoverflow is not supported MathJax.抱歉,MathJax 不支持 Stackoverflow。

Typically you'd do this by storing a single variable with the last value from the calculation, and seeding it with your starting value.通常,您可以通过将计算中的最后一个值存储在一个变量中,并用您的起始值作为种子来实现。 EG:例如:

y = 60000
while True:
    y = .1 * y - 700

Of course, you have to determine when to stop and what to do with the values.当然,您必须确定何时停止以及如何处理这些值。 You certainly want to print them:你当然想打印它们:

y = 60000
while True:
    y = .1 * y - 700
    print(y)

But you probably only want to do it for 100 times or something instead of forever:但你可能只想做 100 次或其他事情而不是永远:

y = 60000
for i in range(12*5):
    y = .1 * y - 700
    print("%d: %f" % (i,y))

And you may want to store them for use later as well, so put those in an array:您可能还想存储它们以备后用,因此将它们放入数组中:

y = 60000
results=[]
for i in range(12*5):
    y = .1 * y - 700
    results.append(y)

print(results)

A regular loop for your task would look like this:您的任务的常规循环如下所示:

loan = 60000
annualinterest = 1.2/100
monthlyinterest = annualinterest/12
monthlyfactor = 1+monthlyinterest
monthlypackback = 700

for month in range(5*12):
    loan = loan * monthlyfactor - monthlypackback
    print(month+1, "{0:.2f}".format(loan))

Note that the monthlyinterest might be discussed for several reasons which are not programming specific:请注意,可能会出于多种原因讨论monthlyinterest ,这些原因并非特定于编程:

a) it may depend when the interest is calculated, ie on which day of the month. a) 可能取决于计算利息的时间,即每月的哪一天。 That may be before or after the payment.这可能是在付款之前或之后。

b) dividing the annual rate by 12 is better for the banks. b) 将年利率除以 12 对银行更好。 It could also be calculated as the 12th root of 1.012.它也可以计算为 1.012 的 12 次方根。

Now, above is a straight forward loop.现在,上面是一个直接的循环。 It has nothing to do with recursion.它与递归无关。 But it can be converted into a recursive call:但它可以转换为递归调用:

def recursive(loan, annualinterestPercentage, monthlyPayback, months):
    if months == 0:
        return loan
    annualinterest = annualinterestPercentage / 100
    monthlyinterest = annualinterest / 12
    monthlyfactor = 1 + monthlyinterest
    return recursive(loan * monthlyfactor - monthlyPayback, annualinterestPercentage, monthlyPayback, months - 1)

The key things are:关键是:

a) a recursive call needs an exit condition. a) 递归调用需要退出条件。 I put it right at the beginning.我一开始就说对了。 The exit condition here is when the remaining months reach 0.这里的退出条件是剩余月份数达到 0 时。

b) the function recursive() calls itself, hopefully with a parameter that goes towards the exit condition. b) 函数recursive()调用自身,希望带有一个接近退出条件的参数。 Here it's month-1 .这是第month-1

You call it like this:你这样称呼它:

print(recursive(60000, 1.2, 700, 60))

Code代码

Using recursion as you asked:按照您的要求使用递归:

def loan_calculator(y, payments, interest, monthly, period, counter=0, amount_left=[]):
  # y -> starting loan (60,000) 
  # payments -> paying $700/month
  # interest -> Interest rate on loan (yearly)
  # monthly -> boolean, if monthly or yearly
  # period -> how many years
  # counter -> number of payments made
  # amount_left -> after each payment how much is left to pay

  if monthly:
    period *= 12
    interest /= (12*100)

  # stopping condition:
  if counter == period:
    return y, amount_left
  else:
    y = (1+interest)*y - payments
    amount_left.append(y)
    counter += 1
    return loan_calculator(y, 700, 1.2, True, 5, counter)

final_payment, all_payments = loan_calculator(6e4, 700, 1.2, True, 5)
print(all_payments)
print(final_payment)

Output输出

[59359.99999999999, 58719.359999999986, 58078.07935999998, 57436.15743935997, 56793.59359679933, 5615
0.38719039612, 55506.53757758651, 54862.04411516409, 54216.90615927925, 53571.12306543852, 52924.6941
88503956, 52277.618882692455, 51629.896501575146, 50981.52639807671, 50332.50792447478, 49682.8404323
9925, 49032.52327283165, 48381.555796104476, 47729.937351900575, 47077.66728925247, 46424.74495654172
, 45771.16970149826, 45116.94087119975, 44462.05781207095, 43806.51986988301, 43150.32638975289, 4249
3.476716142635, 41835.970192858775, 41177.80616305163, 40518.98396921468, 39859.50295318389, 39199.36
245613707, 38538.561818593196, 37877.100380411786, 37214.97748079219, 36552.192458272984, 35888.74465
0731256, 35224.633395381985, 34559.858028777366, 33894.41788680614, 33228.31230469295, 32561.54061699
7634, 31894.102157614627, 31225.996259772237, 30557.222256032004, 29887.779478288034, 29217.667257766
32, 28546.884925024082, 27875.431809949103, 27203.30724175905, 26530.510549000803, 25857.0410595498, 
25182.898100609345, 24508.080998709953, 23832.58907970866, 23156.421668788367, 22479.578090457155, 21
802.057668547608, 21123.859726216153, 20444.983585942366] # This is a list of payments you owe each month                                           
20444.983585942366 # This is your final payment

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

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