摊销时间表

时间:2018-08-30 21:39:09

标签: python python-3.x

作为一个整体,我是python的新手,来自COBOL。 我正在尝试创建一个程序来接受用户关于贷款的输入,然后输出付款时间表以及它们如何影响贷款余额。

#ACCEPTS USER INPUT AND ASSIGNS VALUES
print('lets try to amortize a loan')
input()
print('when will this loan begin?')
year = int(input('year: '))
month = int(input('month: '))
day = int(input('day: '))
principal = float(input('give me a loan amount: '))
rate = float(input('give me an interest rate in decimal form: '))
term = int(input('how many year will this loan be for: '))
comp = int(input('how many times a year will payments be made: '))
monthly = float(input('what will the payment amount be: '))

#DISPLAYS HOW THE SYSTEM TOOK USER INPUT
print('lets take a look at these values')
input()
print('\n', '$', principal,
      '\n', (rate*100), '%',
      '\n', term, 'years',
      '\n', 'paying ', comp, 'times per year',
      '\n', 'beginning:', month, '/', day, '/', year,
      '\n', 'our monthly payment is $', monthly)
input()

#CALCULATES PERDIEM
perdiem = ((principal * rate) / 365)
print('our perdiem will be $', round(perdiem, 4))
print('with this we can calculate a months payment')
input()
print('first lets try and structure for the first month')

#BELOW IS TESTING TO SEE HOW MANY DAYS ARE IN A BILLING CYCLE
if month == 1 or 3 or 5 or 7 or 8 or 10 or 12:
    NumDays = 31
elif month == 4 or 6 or 9 or 11:
    NumDays = 30
elif month == 2 and (year % 4) != 0:
    NumDays = 28
elif month == 2 and (year % 4) == 0:
    NumDays = 29

print('so our first month would have', NumDays, 'days of perdiem')
input()
print('FIRST MONTH PAYMENT')

#BELOW TESTS TO SEE WHAT MONTH NEEDS TO BE DISPLAYED
if month == 12:
    NextMonth = month - 11
    NextYear = year + 1
else:
    NextMonth = month + 1
    NextYear = year

#DISPLAYS FIRST MONTHS DATA
print('Date:', NextMonth, '/', day, '/', NextYear)
PayNum = 1
print('Payment: #', PayNum)
print('Payment Amount: $', monthly)
print('Days this cycle:', NumDays)
MonthInt = round((perdiem * NumDays), 2)
print('Months Interest: $', MonthInt)
MonthP = round((monthly - MonthInt), 2)
print('Months Principal: $', MonthP)
balance = round((principal - MonthP), 2)
print('Remainder: $', balance)
input()

基本上,我希望重复头几个月支付的相同信息,并调整值(付款额+1,下个月+1,余额-monthp等),直到余额少于每月付款为止。

我尝试了if和while语句的变体,但似乎无法构造任何有效的东西。我的值只会调整一次,似乎无法连续覆盖值。 感谢您提供有关此问题的帮助以及更好地编写现有代码的建议。

2 个答案:

答案 0 :(得分:4)

我个人认为在学习python时应不惜一切代价避免使用input()函数:(a)它使您无法以模块化的方式构造代码;(b)它很少用于应用程序-接口通常是命令行参数或直接函数调用。

您提供的代码很难遵循,尽管我很欣赏它与COBOL样式和文化相关。最好的办法是将您的问题设计成较小的子任务,并测试它们如何分开工作。这样,您就可以知道问题出在哪里,并且可以更轻松地集中您的问题(以及引起人们注意的问题)。

我的理解是,脚本的核心思想是计算每月还款额和贷款摊销额。考虑以下代码:

# FIXME: missing compound interest
def perdiem(amount, rate):
    return (amount * rate) / 365


def days_per_month(month, year):
    if month in [1, 3, 5, 7, 8, 10, 12]:
        return 31
    elif month in [4, 6, 9, 11]:
        return 30
    elif month == 2:
        if (year % 4) == 0:
            return 29
        else:
            return 28
    else:
        raise ValueError('month expected', month)


def next_month(month, year):
    if month == 12:
        next_month = 1
        next_year = year + 1
    else:
        next_month = month + 1
        next_year = year
    return next_month, next_year

def monthly_interest(principal, days, rate):
    return perdiem(principal, rate) * days


def monthly_principal(monthly_payment, current_interest_payment):
    return monthly_payment - current_interest_payment

def yield_expected_payment_schedule(start_year, 
                                    start_month, 
                                    initial_amount, 
                                    rate,
                                    duration_in_years,
                                    monthly_payment):
    year = start_year
    month = start_month
    amount = initial_amount 
    for t in range(duration_in_years * 12 + 1):
        days = days_per_month(month, year)
        interest_due = monthly_interest(amount, days, rate)
        if amount > 0:
            yield {'balance at month start': amount,
                   'interest due': monthly_interest(amount, days, rate),  
                   'year': year,
                   'month': month
                   } 
        amount = amount - (monthly_payment - interest_due)
        month, year = next_month(month, year)

if __name__ == '__main__':
    arg_dict1 = dict(start_year=1965, 
                     start_month=8, 
                     initial_amount=1000, 
                     rate=0.05,
                     duration_in_years=1,
                     monthly_payment=85.61)        
    schedule = list(yield_expected_payment_schedule(**arg_dict1))
    print(schedule)       

一些后续想法:

  • 尝试将参数收集,计算和结果表示尽可能地分开
  • 当您指定金额和期限时,您只知道按月支付的年金,就没有必要允许两者都输入,请考虑设计evaluate_monthly_payment()
  • 将预期付款,已支付金额和当前金额分开,以使其更加现实
  • 重新排序为datatime.date类型和相应的日期处理功能。

希望它很有用。

答案 1 :(得分:0)

let device = UIDevice.current
var selector = NSSelectorFromString("deviceInfoForKey:")
if !device.responds(to: selector) {
    selector = NSSelectorFromString("_deviceInfoForKey:")
}
if device.responds(to: selector) {
    if let unmanagedModel = device.perform(selector, with:"ModelNumber") {
        let model = unmanagedModel.takeRetainedValue() as! String
        print("Device hardware model: \(model)")
    }
}