I'm currently working through hyperskill projects. The way I've done this code probably isn't ideal but i'm just trying to work in lists / classes / objects to stuff as I go.
On Pycharm it highlights all the self.methods under the if statement with " 'int' object is not callable " (or float) - but the code works as expected? Wondering why this would be.
Putting self.everything under the init with = None makes the highlighting / warning go away, but the code doesn't work.
This is also my first question, sorry if it is too broad. I tried looking for answers through other questions. Also not sure if I should be pasting all the code as I'm not sure which part is relevant.
from math import ceil, floor, pow, log
class LoanCalc:
options = ['Enter the loan principal:', 'Enter the monthly payment', 'Enter the loan interest:',
'Enter the number of periods:', 'Enter the annuity payment:']
def __init__(self):
pass
def loan_principle(self):
self.loan_principle = int(input(self.options[0]))
def monthly_payment(self):
self.monthly_payment = int(input(self.options[1]))
def loan_interest(self):
self.loan_interest = float(input(self.options[2]))
def i(self):
self.i = self.loan_interest / (12 * 100)
def periods(self):
self.periods = int(input(self.options[3]))
def a(self):
self.a = float(input(self.options[4]))
def main(self):
inp_options = input('''\
What do you want to calculate?
type "n" - for number of monthly payments,
type "a" for annuity monthly payment amount,
type "p" - for the monthly payment:
''')
if inp_options == 'n':
self.loan_principle()
self.monthly_payment()
self.loan_interest()
self. i()
n_months = log(self.monthly_payment /
(self.monthly_payment - self.i * self.loan_principle), 1 + self.i)
years = 0
if n_months < 11:
print(f'It will take {ceil(n_months)} months to repay this loan!')
elif n_months >= 12:
while n_months > 11:
n_months -= 12
years += 1
print(f'It will take {years} years and {ceil(n_months)} months to repay this loan!')
elif inp_options == 'p':
self.a()
self.periods()
self.loan_interest()
self. i()
loan_principal = self.a / ((self.i * ((1 + self.i) ** self.periods)) / (((1 + self.i) ** self.periods) - 1))
print(f'Your loan principal = {floor(loan_principal)}!')
elif inp_options == 'a':
self.loan_principle()
self.periods()
self.loan_interest()
self. i()
ann = ceil(self.loan_principle * ((self.i * pow(1 + self.i, self.periods)) /
(pow(1 + self.i, self.periods) - 1)))
print(f'Your monthly payment = {ann}!')
loan_calculator = LoanCalc()
loan_calculator.main()
Related
I'm working on a small personal project in Python 3 where you put in a name and get there weekly wages. I want to add a feature where an admin can come in and add a person to the workers, including their wages. Here's what I have as for people so far:
worker = input("Name: ")
if worker == "Anne":
def calcweeklywages(totalhours, hourlywage):
'''Return the total weekly wages for a worker working totalHours,
with a given regular hourlyWage. Include overtime for hours over 40.
'''
if totalhours <= 40:
totalwages = hourlywage * totalhours
else:
overtime = totalhours - 40
totalwages = hourlywage * 40 + (1.5 * hourlywage) * overtime
return totalwages
def main():
hours = float(input('Enter hours worked: '))
wage = 34
total = calcweeklywages(hours, wage)
print('Wages for {hours} hours at ${wage:.2f} per hour are ${total:.2f}.'
.format(**locals()))
main()
elif worker == "Johnathan":
def calcweeklywages(totalhours, hourlywage):
'''Return the total weekly wages for a worker working totalHours,
with a given regular hourlyWage. Include overtime for hours over 40.
'''
if totalhours <= 40:
totalwages = hourlywage * totalhours
else:
overtime = totalhours - 40
totalwages = hourlywage * 40 + (1.5 * hourlywage) * overtime
return totalwages
def main():
hours = float(input('Enter hours worked: '))
wage = 30
total = calcweeklywages(hours, wage)
print('Wages for {hours} hours at ${wage:.2f} per hour are ${total:.2f}.'
.format(**locals()))
main()
I want to add a part where if someone types in a code or something that they're an admin, it will let them add a person or edit an existing persons information.
I am not sure how you intend to deploy it, but even from the coding standpoint as it stands it will not behave the way you expect it to. I am guessing you are doing this just to learn. So, let me point out a couple of places where you have understood the basics wrong and a purely pedagogic example of how it could be done. Bear in mind that I strongly discourage from using this in any real context.
You have defined the function calcweeklywages twice in your code. When in fact it has to be defined just once. If you want to use the code, you call it, like you have done so in the main() program. The function works exactly the same for both your workers, so to get different weekly wages you pass different wages. But, how do you link their respective wages to their names (or some representation of them in your code)?
This is a good example where object oriented programming is used. A brief and entertaining primer is here. As for the code, it will look like this,
class Employee:
def __init__(self, Name, Wage = 0, Hours = 0):
self.Name = Name
self.Wage = Wage
self.Hours = Hours
def calcweeklywages(Employee, totalhours):
'''Return the total weekly wages for a worker working totalHours,
with a given regular hourlyWage. Include overtime for hours over 40.
'''
hourlywage = Employee.Wage
if totalhours <= 40:
totalwages = hourlywage * totalhours
else:
overtime = totalhours - 40
totalwages = hourlywage * 40 + (1.5 * hourlywage) * overtime
return totalwages
# In your main body, you just test the functionality
EmployeeList = []
EmployeeList.append(Employee("Anne", 34))
EmployeeList.append(Employee("Johnathan", 30))
while(True):
action = input('Exit? (y/n): ')
if(action == 'y'):
break
else:
name = input('Enter the employee\'s name: ')
for Employee in EmployeeList:
if(Employee.Name == name):
Person = Employee
hours = int(input('Enter the number of hours worked: '))
print('Wages for', hours, 'hours at', Person.Wage,'per hour is', calcweeklywages(Person, hours))
EDIT: I am sorry, I forgot about the admin part. But here goes,
class Employee:
def __init__(self, Name, Wage = 0, Hours = 0, Admin = False, code = ''):
self.Name = Name
self.Wage = Wage
self.Hours = Hours
self.Admin = Admin
self.code = code
def calcweeklywages(Employee, totalhours):
'''Return the total weekly wages for a worker working totalHours,
with a given regular hourlyWage. Include overtime for hours over 40.
'''
hourlywage = Employee.Wage
if totalhours <= 40:
totalwages = hourlywage * totalhours
else:
overtime = totalhours - 40
totalwages = hourlywage * 40 + (1.5 * hourlywage) * overtime
return totalwages
# In your main body, you just test the functionality
EmployeeList = []
EmployeeList.append(Employee("Anne", 34))
EmployeeList.append(Employee("Johnathan", 30))
EmployeeList.append(Employee("Mr. Admin", 50, 0, True, 'Open Sesame'))
while(True):
action = int(input('Enter action :\n 1. Exit.\n 2. Add new employee.\n 3. Compute weekly wage\n'))
if(action == 1):
break
elif(action == 2):
AdminName = input('Enter operator name : ')
Flag = False
for EmployeeInst in EmployeeList:
if((EmployeeInst.Name == AdminName) & (EmployeeInst.Admin)):
code = input('Enter code :')
if(code != EmployeeInst.code):
break
NewName = input('New Employee name? :')
NewWage = int(input('New employee wage? :'))
EmployeeList.append(Employee(NewName, NewWage))
Flag = True
if(not Flag):
print('Wrong Credentials')
break
elif(action == 3):
name = input('Enter the employee\'s name: ')
for Employee in EmployeeList:
if(Employee.Name == name):
Person = Employee
hours = int(input('Enter the number of hours worked: '))
print('Wages for', hours, 'hours at', Person.Wage,'per hour is', calcweeklywages(Person, hours))
else:
print('Input out of range')
break
But again, the session is not persistent between different kernel runs. There is no real "security", this is just an exploration of Python's object oriented code. Please do not use this for any real application. There is a lot more that goes with all this. You need to store it in a secure file, have some GUI front end etc etc. There are far wiser users who will guide you to implement the system as a whole. All the best with your studies. Cheers.
So, I'm having a lot of trouble inputting my answer into the grader for the MIT Intro to CS in Python course on edX.
The specific problem ask for a program that will calculate the interest on a credit card given the monthly payment rate, interest rate, and initial balance.
I'm pretty sure my code is fine, I just can't get the grader to accept it.
I've tried changing the code to account for the names of the variables that the grader wants and removed the input prompts, function wrapper and return calls, but it still doesn't work.
Here is my initial code:
from math import *
b = float(input("balance = "))
r = float(input("annualInterestRate = "))
p = float(input("monthlyPaymentRate = "))
bval = []
def interest(b, r, p):
bal = (b - (b * p))
def update(bal, r):
balance = (bal + (r / 12.0) * bal)
return balance
if len(bval) < 12:
bval.append(update(bal, r))
return(interest(bval[-1], r, p))
elif len(bval) == 12:
return print("Remaning balance: " + "{:.2f}".format(bval[-1]))
interest(b, r, p)
And here is what it was modified to:
from math import *
bval = []
bal = (blance - (balance * monthlyPaymentRate))
def update(balance, annualInterestRate):
bal = round((balance + (annualInterestRate / 12.0) * balance), 2)
return bal
if len(bval) < 12:
bval.append(update(bal, annualInterestRate))
(interest(bval[-1], annualInterestRate, monthlyPaymentRate))
elif len(bval) == 12:
print("Remaning balance: " + "{:.2f}".format(bval[-1]))
Any help?
I'm new to Python, currently doing the MIT edX course. We had a problem to complete where we had to use the bisection method to find the lowest payment a person had to make to pay off a credit card dept in a year.We were given the balance and the annual interest rate. My code below works but it does not look correct to me. Does anyone have any insight in this? Thanks
def payment(balance, annualInterestRate):
newBalance = 0
monthlyInterest = annualInterestRate / 12
maxPaybal = (balance * (1 + monthlyInterest) ** 12) / 12
minPaybal = balance/12
while round(newBalance, 2) != 0.01 or round(newBalance, 2) != 0.00:
guess = (minPaybal + maxPaybal) / 2.0
newBalance = balance
months = 12
while months > 0:
prevBalance = newBalance - guess
uptdBalance = prevBalance + (prevBalance * monthlyInterest)
newBalance = uptdBalance
months -= 1
if round(newBalance, 2) == 0.01 or round(newBalance, 2) == 0.00:
return "Lowest Payment: ", round(guess, 2)
elif newBalance < 0.00:
maxPaybal = guess
else:
minPaybal = guess
print(payment(balance, annualInterestRate))
Folks,
I am getting my head stuck in knots here with problem 3 from PS1 in MIT6.00. I have written a couple of functions (one bisection search, and one function modelling the credit card debt). The problem is that it converges on a solution that gives a slightly positive remaining credit card balance. I could lower the tolerance in the bisection search, but I wanted to know if there was some more elegant way of making this optimiser return only negative results.
Cheers,
Aiden
code:
import numpy as np
def bisection(a, b, fun, tol, var = None):
"""Note that this only works if you put the independant variable
as the first argument in the parameter """
#def tstr(x):
# return 2*(x**2) - 3*x + 1
#sol = bisection(0,0.9,tstr,0.1)
c = (a+b)/2.0
if var != None:
arga = var[:]
argc = var[:]
arga.insert(0,a)
argc.insert(0,c)
else:
arga = a
argc = c
if (b-a)/2.0 <= tol:
#Debugging print statement 1:
#print 'SOL1: c = ', c
if var != None:
return [c] + fun(argc)
else:
return c
if fun(argc)[0] == 0:
if var != None:
return [c] + fun(argc)
else:
return c
elif fun(arga)[0]*fun(argc)[0] < 0:
b = c
else:
a = c
return bisection(a, b, fun, tol, var)
"""
Now we have defined a version of the paidOff function to work
with the bisection method"""
def paidOffBis(args):#(Pay, Bal, Apr):
"""Tester for Bisection Implementation"""
# TEST SIZE OF args:
if (type(args) != list)|(np.size(args) != 3):
print 'Incorrect size or type of input, input size:', np.size(args), '-', args
return None
Pay, Bal, Apr = args
Mpr = Apr/12.0
Baln = Bal
Nm = 0
for n in range(12):
Baln = Baln*(1 + Mpr) - Pay
if (Baln < 0)&(Nm == 0):
Nm = n + 1
if Baln < 0:
return [Baln, Nm]
else:
return [Baln, Nm]
Out_Bal = float(raw_input('Enter the outstanding balance on your credit card: '))
Apr = float(raw_input('Enter the annual credit card interest rate as a decimal: '))
varin = [Out_Bal, Apr]
#(Out_Bal*(1 + (Apr/12.0))**12.0)/12.0
sol = bisection(Out_Bal/12.0, Out_Bal, paidOffBis, 0.01, varin)
print 'RESULT'
print 'Monthly payment to pay off debt in 1 year: $%.2f' % sol[0]
print 'Number of months needed:', sol[2]
print 'Balance: $%.2f' % sol[1]
To ensure a balance less than or equal to zero you need to set your conditional statements correctly - you need to keep searching till that criteria is met. You asked for ... a more elegant way .... Using descriptive names for your variables and keeping it simple would certainly improve your code. Here is one way to craft a solution using a bisection search.
annualInterestRate = .1
balance = 1000
def balance_after_one_year(balance, annualInterestRate, payment):
'''Calculate the balance after one year of interest and payments.
balance --> int or float
annualInterestRate --> float between 0 and 1
payment --> float
returns float
'''
for _ in xrange(12):
balance = (balance - payment) * (1 + annualInterestRate / 12.0)
return balance
def min_payment(balance, annualInterestRate, tolerance = .01):
'''Find the minimum payment to pay off a loan.
Uses a bisection search.
Ensures balance is not positive.
balance --> float, int
annualInterestRate --> float less than one
tolerance --> float
'''
# we want the tolerance to be negative
# this isn't strictly a tolerance, it is a lower limit
tolerance = -abs(tolerance)
hi = balance
lo = 0
while True:
payment = (hi + lo) / 2.0
tmp_balance = balance_after_one_year(balance, annualInterestRate, payment)
if tmp_balance < tolerance:
hi = payment
# ensure balance is not positive
elif tmp_balance > 0:
lo = payment
else:
return payment, tmp_balance
Usage:
min_pmt, final_balance = min_payment(balance, annualInterestRate)
print 'minimum payment', min_pmt
print 'final balance', final_balance
I just started college and I am writing this code out for my college class and it keeps sending an error. Any enlightenment will help, maybe the problem is that I'm half asleep.
here is the code
def main():
overtime = int(0)
totaloverpay = float(0)
hours = int(input('How many hours did you work? NOTE** Hours can not exceed 86 or be less than 8 '))
while hours > 86 or hours < 8:
print('ERROR: Insufficient input. Try again')
hours = int(input('How many hours did you work? NOTE** Hours can not exceed 86 or be less than 8 '))
payrate = float(input('What is the payrate per hour for this employee? NOTE** Payrate can not exceed $50.00 or be less than $7.00 '))
while payrate > 50.00 or payrate < 7.00:
print('ERROR: Insufficient input. Try again')
payrate = float(input('What is the payrate per hour for this employee? NOTE** Payrate can not exceed $50.00 or be less than $7.00 '))
workhours(hours, payrate, overtime)
def workhours(hours, payrate, overtime):
if hours > 40:
overtime = (hours - 40) * -1
else:
regtime = hours + 0
paydistribution(hours, payrate, regtime, overtime)
def paydistribution(hours, payrate, regtime, overtime):
if hours >= 40:
halfrate = float(payrate * 0.5)
overpay = halfrate + payrate
totaloverpay = float(overpay * hours)
if hours < 40:
regpay = hours * payrate
display(hours, payrate, regpay, regtime, overtime)
def display(hours, payrate, regpay, regtime, overtime):
total = float(regpay + totaloverpay)
print(' Payroll Information')
print('Payrate :', format(payrate, '0.2f'))
print('Regular Hours :', format(regtime))
print('Overtime Hours:', format(overtime))
print('Regular Pay :', format(regpay, '6.2f'))
print('Overtime Pay :', format(totaloverpay, '7.2f'))
print('Total Pay :', format(total, '7.2f'))
main()
totaloverplay is not defined in any function below main in which it is referred to, or as a global variable. If you want it to be global, define it outside of the main function's scope.
This looks like a great use-case for a class rather than relying on functional programming.
from decimal import Decimal # more precision than floating point
MINIMUM_WAGE = Decimal("7.25")
OVERTIME_RATE = Decimal("1.5")
class Employee(object):
def __init__(self,first,last,MI="",payrate=MINIMUM_WAGE):
self.first = first.capitalize()
self.last = last.capitalize()
self.MI = MI.upper()
if not MI.endswith("."): self.MI += "."
self.payrate = payrate
self.hours = 0
#property
def name(self, reversed_=False):
return "{} {} {}".format(self.first,self.MI,self.last)
#property
def alphabetize(self):
return "{}, {}".format(self.last, self.first)
def payroll(self,numweeks=1):
regularhours = min(40*numweeks,self.hours)
OThours = max(0,self.hours-regularhours)
regularpay = regularhours * self.payrate
OTpay = round(OThours * self.payrate * OVERTIME_RATE,2)
return {"reghours":regularhours,
"overtime":OThours,
"regpay":regularpay,
"OTpay":OTpay,
"total":regularpay + OTpay}
def sethoursworked(self,amt):
self.hours = amt
def display(employee):
payrollinfo = employee.payroll()
print("{:^30}".format("Payroll Information"))
print("{:>30}".format(employee.name))
print("Payrate:{:>22}".format(employee.payrate))
print("Hours:{:>24}".format(payrollinfo['reghours']))
print("Overtime Hours:{:>15}".format(payrollinfo['overtime']))
print("Regular Pay:{:>18}".format(payrollinfo['regpay']))
print("Overtime Pay:{:>17}".format(payrollinfo['OTpay']))
print("-"*30)
print("Total Pay:{:>20}".format(payrollinfo['total']))
Adam = Employee("Adam","Smith","D")
Adam.sethoursworked(51)
display(Adam)
OUTPUT:
Payroll Information
Adam D. Smith
Payrate: 7.25
Hours: 40
Overtime Hours: 11
Regular Pay: 290.00
Overtime Pay: 119.62
------------------------------
Total Pay: 409.62
You should not get in the habit of using global; it's usually a sign that you're heading in the wrong direction. Instead, pass the variables you need around explicitly, using function arguments and return statements. Also, don't pass functions arguments they don't need to do their job, and prefer default arguments or explicit constants to "magic numbers". For example:
def workhours(hours, threshold=40):
if hours > threshold:
overtime = hours - threshold
regtime = threshold
else:
overtime = 0
regtime = hours
return regtime, overtime
def paydistribution(payrate, regtime, overtime, otrate=1.5):
regpay = regtime * payrate
overpay = overtime * payrate * otrate
return regpay, overpay
Now main can call:
regtime, overtime = workhours(hours)
regpay, overpay = paydistribution(payrate, regtime, overtime)
display(hours, payrate, regpay, regtime, overtime)
This keeps the flow mostly in main while letting the other functions do just their specific bits of the task.
In your position, I would also consider having a separate function to take user input, which loops until they provide something acceptable. An appropriate definition, for example:
def user_input(prompt, min_, max_):
Here is another cleaned-up version:
from textwrap import dedent
import sys
if sys.hexversion < 0x3000000:
# Python 2.x
inp = raw_input
else:
# Python 3.x
inp = input
MIN_HOURS = 8.
MAX_HOURS = 86.
MIN_RATE = 7.
MAX_RATE = 50.
OVERTIME_CUTOFF = 40.
OVERTIME_BONUS = 0.5
def get_float(prompt, lo=None, hi=None):
while True:
try:
val = float(inp(prompt))
if lo is not None and val < lo:
print("Value must be >= {}".format(lo))
elif hi is not None and val > hi:
print("Value must be <= {}".format(hi))
else:
return val
except ValueError:
print("Please enter a number")
def main():
hours = get_float("How many hours did you work? ", MIN_HOURS, MAX_HOURS)
rate = get_float("What is the hourly payrate? ", MIN_RATE, MAX_RATE)
time = min(hours, OVERTIME_CUTOFF)
pay = time * rate
overtime = max(0., hours - OVERTIME_CUTOFF)
overpay = overtime * rate * (1. + OVERTIME_BONUS)
print(dedent("""
Payroll Information
Payrate : $ {rate:>7.2f}
Regular Hours : {time:>4.0f} h
Regular Pay : $ {pay:>7.2f}
Overtime Hours: {overtime:>4.0f} h
Overtime Pay : $ {overpay:>7.2f}
Total Pay : $ {total:>7.2f}
""").format(rate=rate, time=time, pay=pay, overtime=overtime, overpay=overpay, total=pay+overpay))
if __name__=="__main__":
main()
which runs like
How many hours did you work? 46
What is the hourly payrate? 11
Payroll Information
Payrate : $ 11.00
Regular Hours : 40 h
Regular Pay : $ 440.00
Overtime Hours: 6 h
Overtime Pay : $ 99.00
Total Pay : $ 539.00