rody401
rody401

Reputation: 109

Years and months output not formatting properly

When I try to implement this function of no_payment() in my python script:

import math
import argparse

parse = argparse.ArgumentParser(usage='Differential calculator that calculates the per month payment on a decreasing'
                                      'principal amount')
parse.add_argument('--type', '-t', type=str, required=True, help='diff = differential, annuity = standard, fixed payments') #error code
# cant compute with diff argument selected, as payment each month is different
parse.add_argument('--payment', '-p', type=float, required=False, help='monthly payment amount')
parse.add_argument('--principal', '-P', type=float, required=False, help='principal amount of the loan')
parse.add_argument('--periods', '-m', type=int, required=False, help='number of payments required to pay the loan')
parse.add_argument('--interest', '-i', type=float, required=True, help='interest rate (as integer, not converted)') #error code
args = parse.parse_args()

 
def no_payments():

    i = args.interest / (12 * 100)
    month_no = math.log(args.payment / (args.payment - i * args.principal), 1 + i)
    overpayment = args.principal * args.interest
    year_count = math.ceil(month_no // 12)
    month_count = math.ceil(month_no % 12)
    if 1 < month_no <= 12:
        print(f'It will take {month_count} months to repay this loan!')
    elif month_no == 1:
        print(f'It will take 1 month to repay this loan!')
    elif month_no == 12:
        print(f'It will take 1 year to repay this loan!')
    elif 12 < month_no < 24 and month_count == 1:
        print(f'It will take {year_count} year and 1 month to repay this loan!')
    elif 12 < month_no < 24 and month_count > 1:
        print(f'It will take {year_count} year and {month_count} months to repay this loan!')
    elif month_no >= 24 and month_count == 1:
        print(f'It will take {year_count} years and {month_count} month to repay this loan!')
    elif month_no >= 24 and month_count > 1:
        print(f'It will take {year_count} years and {month_count} months to repay this loan!')

    print(f'Overpayment = {overpayment}')


# error codes thrown if interest and type are not inputted


if args.interest is None:
    print('Incorrect Parameters')
elif args.type is None:
    print('Incorrect Parameters')


if args.type == 'annuity' and args.payment is None:
    ann_calc()
elif args.type == 'diff' and args.payment is None:
    diff_calc()
elif args.type == 'annuity' and args.principal is None:
    princ()
elif args.type == 'annuity' and args.periods is None:
    no_payments()

With a given argument of --type=annuity --principal=500000 --payment=23000 --interest=7.8.
The output should be 2 years but it comes out to be 1 year and 12 months. What do I have to change to make the output as 2 years?

Upvotes: 1

Views: 35

Answers (1)

arcee123
arcee123

Reputation: 243

on line 8m, your configuration states:

 month_no = math.log(args.payment / (args.payment - i * args.principal), 1 + I)

using the arguments you stated in your question, this results in a value of 23.513122662562726

This is the reason why you are receiving 1 year and 12 months in your response, because technically it's 23 months, then converted to 24 months when rounded.

you have two options:

  1. round up to 24 months, if the business logic states
  2. remove the math.ceil, and allow the number of months to be shown as fractions.

This answers your immediate question.

For the long term solution, I would recommend a reducing classification method with your date calculations. For example:

month_no = 24 (for your example)
years = math.floor(month_no / 12). -> 2
months = (month_no - (years * 12)) -> 24 - (2 * 12) -> 0

another example:

month_no = 26 (for your example)
years = math.floor(month_no / 12). -> 2
months = (month_no - (years * 12)) -> 26 - (2 * 12) -> 2

from there you can use string injection to push your print statement

yr = '{} years'.format(years) if years > 1 else '1 year' if years = 1 else ''
mo = 'and {} months'.format(months) if months > 1 else 'and 1 month' if months = 1 else ''

print('It will take {years}{months} to repay this loan!'.format(years,months))

here's my example:

import math
import argparse

#--type=annuity --principal=500000 --payment=23000 --interest=7.8
def no_payments(args):

    i = args['interest'] / (12 * 100)
    month_no = round(math.log(args['payment'] / (args['payment'] - i * args['principal']), 1 + i))
    overpayment = args['principal'] * args['interest']
    year_count = math.ceil(month_no // 12)
    month_count = math.ceil(month_no % 12)
    
    print("month no")
    print(month_no, month_count, math.ceil(24 % 12))
    years = math.floor(month_no / 12) #-> 2
    months = (month_no - (years * 12)) # -> 26 - (2 * 12) #-> 2
    yr = '{} years'.format(years) if years > 1 else '1 year' if years == 1 else ''
    mo = 'and {} months'.format(months) if months > 1 else 'and 1 month' if months == 1 else ''
    
    print('It will take {}{} to repay this loan!'.format(yr,mo))

args = {
    'type': 'annuity',
    'principal': 500000,
    'payment': 23000,
    'interest': 7.8
}
no_payments(args)

Upvotes: 1

Related Questions