Calculate change from paid amount - python

Why is this code creating an infinite loop? I would think this should be an appropriate solution for this type of problem. For example, if the price was $5 and you paid $5.47, the program would print:
Quarters: 1
Dimes: 2
Nickels: 0
Pennies: 2
However, an infinite loop occurs and I'm not sure why. Anyone know the reason?
price = round(float(input("Enter the price: ")), 2)
print price
paid = round(float(input("Enter the amount paid: ")), 2)
print paid
change = round(float(paid - price), 2)
print change
quarters = 0
dimes = 0
nickels = 0
pennies = 0
while change > 0.00:
print change
if change >= .25:
change = change - .25
quarters += 1
continue
elif change >= .1:
change = change - .1
dimes += 1
continue
elif change >= .05:
change = change - .05
nickels += 1
elif change >= .01:
change = change - .01
pennies += 1
print "Quarters: " + str(quarters)
print "Dimes: " + str(dimes)
print "Nickels: " + str(nickels)
print "Pennies: " + str(pennies)

Rather than dealing with loops, I would suggest just subtracing off the change that you already gathered, prioritizing larger coins.
price = float(input("Enter the price: "))
paid = float(input("Enter the amount paid: "))
change = paid - price
if change < 0:
raise ValueError('Not enough paid')
quarters = change // 0.25
dimes = (change - (0.25 * quarters)) // 0.10
nickels = (change - (0.25 * quarters) - (0.10 * dimes)) // 0.05
pennies = 100 * (change - (0.25 * quarters) - (0.10 * dimes) - (0.05 * nickels))
print("Quarters: {:.0f}".format(quarters))
print("Dimes: {:.0f}".format(dimes))
print("Nickels: {:.0f}".format(nickels))
print("Pennies: {:.0f}".format(pennies))

There's one minor bug in the code which causes the program to only work correctly if price and amount paid are interchanged (e.g. price = 2, paid = 1). But that is not the issue causing the infinite loop.
Your code creates an infinite loop for e.g. the following arguments:
price: 5.6
paid: 5.4
The reason for the infinite loop can be seen from your own print output:
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
0.009999999999999275
...
Since change < 0.01, no if clause applies and thus the loop is never left.
How could you solve the problem more robustly?
Here's a sketch
from math import floor
change = paid - price
quarters = int(floor(change / 0.25))
change -= quarters * 0.25
dimes = int(floor(change / 0.1))
change -= dimes * 0.1
nickels = int(floor(change / 0.05))
change -= nickels * 0.05
pennies = int(floor(change / 0.01))
change -= pennies * 0.01
remaining = change
print("Quarters:", quarters)
print("Dimes:", dimes)
print("Nickels:", nickels)
print("Pennies:", pennies)
Personally I would also condense this into a loop over the coin type:
increments = {"quarter":0.25, "dimes": 0.1, "nickels": 0.05, "pennies": 0.01}
change_parts = {}
for inc_name, inc in increments.items():
amount = int(floor(change / inc))
print(inc_name, inc, amount)
change -= amount * inc
change_parts[inc_name] = amount
for inc_name, amount in change_parts.items():
print(inc_name + ":", amount)

Related

Working on a problem to find the lowest number at which we can pay off debt in a year. Answer is a bit off

I am taking a course on edx and trying to solve a problem using bisection to calculate a monthly payment at which we can pay off the debt in a year. I have coded a solution but the results are a bit off than expected. Code is below. Answer code shared by edx is also listed beneath. Can you please share why my code is not giving same results? I am trying to get to to 2 decimal places accuracy.
balance=float(input('balance = '))
annualInterestRate=float(input('annualInterestRate = '))
remainingbalance=balance
low=float(remainingbalance/12)
high=float(remainingbalance*((1+(annualInterestRate/12))**12)/12.0)
if remainingbalance>0.01 or remaningbalance<0.01:
remainingbalance=balance
increment=round(float((high+low)/2), 2)
for i in range(1, 13):
unpaidbalance=remainingbalance-increment
interest=(annualInterestRate/12) * unpaidbalance
remainingbalance=round(unpaidbalance + interest, 2)
if remainingbalance>0.01:
low=increment
elif remainingbalance<-0.01:
high=increment
print('Lowest Payment: ', increment)
Sample code for solution provided by edx
init_balance = balance
monthlyInterestRate = annualInterestRate/12
lower = init_balance/12
upper = (init_balance * (1 + monthlyInterestRate)**12)/12.0
epsilon = 0.03
while abs(balance) > epsilon:
monthlyPaymentRate = (upper + lower)/2
balance = init_balance
for i in range(12):
balance = balance - monthlyPaymentRate + ((balance - monthlyPaymentRate) * monthlyInterestRate)
if balance > epsilon:
lower = monthlyPaymentRate
elif balance < -epsilon:
upper = monthlyPaymentRate
else:
break
print('Lowest Payment:', round(monthlyPaymentRate, 2))
My Code Results:
balance = 320000
annualInterestRate = 0.2
Lowest Payment: 29591.88
Edx Results:
balance = 320000
annualInterestRate = 0.2
Lowest Payment: 29157.09

Why is string not recognizing my output as an integer

balance = int(100)
balance *= 0.05 + balance
balance *= 0.05 + balance
balance *= 0.05 + balance
print (int(round ( balance, '.2f' )))
im trying to calculate what 100$ interest would be after 3 years compound interest.
I originally tried this
balance = 100
balance *= 0.05 + balance
balance *= 0.05 + balance
balance *= 0.05 + balance
print (format( balance, '.2f' ))
but my formatting caused the answer to be in the trillions instead of a 5 digit float.
You're multiplying the balances. Try this:
balance = int(100)
balance = balance * 0.05 + balance
balance = balance * 0.05 + balance
balance = balance * 0.05 + balance
print("{:.02f}".format(balance))
You have your operator precedence incorrect: the assignment operator is last. Thus, what you've done is
balance = balance * (0.05 + balance)
Instead, try one of the canonical ways to express interest:
rate = 0.05
balance += balance * rate
or
balance *= (1 + rate)
The parentheses aren't needed, but will help you read this.
Also, you might make a parameter (variable) for your repetition:
limit = 3
for year in range(limit):
balance *= 1 + rate
print("{:.02f}".format(balance))
You should pay attention to order of operations. balance *= 0.05 + balance will add 0.05 and balance before multiplying it to balance. What you'd want is balance = balance + balance * 0.05 or balance = balance * 1.05.
You can create a function to calculate compound interest to make it easier:
def comp_int(balance, rate, years):
return balance * (1 + rate)**years
balance = 100
rate = 0.05
years = 3
new_bal = comp_int(balance, rate, years)
print(f'{new_bal:.2f}')

Figuring out money change in python

I have an assignment where I have to prompt the user for cost of a product and amount paid, I have to output change in pennies, dimes, quarters, $1, $5, $20, $50, and $100, for example: The cost of the item is $19.99 and the client pays with a $50 bill. The change to be provided is 1 $20 bill, one $10 bill, and one penny.
I am confused how to get an output like that though, any help would be greatly appreciated, heres what I have so far
cost = float(input('Cost: '))
amount_paid = float(input('Amount paid: '))
penny = 0.01
dime = 0.10
quarter = 0.25
dollar_1 = 1.00
dollar_5 = 5.00
dollar_10 = 10.00
dollar_20 = 20.00
dollar_50 = 50.00
dollar_100 = 100.00
change = cost - amount_paid
if amount_paid < cost:
print('Error')
I dont know what to do next
A common misstep here is to use floats. You should instead convert everything to the smallest whole unit (a cent) and use integer math. Floating point math is...fuzzy.
currencies = {"penny": 1,
"nickel": 5,
"dime": 10,
"quarter": 25,
"dollar": 1_00,
"five": 5_00,
"ten": 10_00,
"twenty": 20_00,
"fifty": 50_00,
"hundred": 100_00}
# never seen that numeric notation before? It's safe to embed underscores
# in numerical literals! It's often used for large numbers in place of
# commas, but it makes sense here in place of a period.
Then you should only need to define a dictionary for the result, and use divmod to find how many of the denomination can fit in the amount left due.
change_due = {}
for denomination, amt in reversed(currencies.items()):
if amt < amt_due:
d, m = divmod(amt_due, amt)
change_due[denomination] = d
amt_due = m
welcome to stackoverflow! I wrote the code for you and this is how it works. Basically it sees each currency and uses integer division // to see how many integers can fit in. It then subtracts that amount from the remaining change and the process continues. Please ask if you don't understand something, or if you think there is an error.
Code:
cost = float(input('Cost: '))
amount_paid = float(input('Amount paid: '))
penny = 0.01
dime = 0.10
quarter = 0.25
dollar_1 = 1.00
dollar_5 = 5.00
dollar_10 = 10.00
dollar_20 = 20.00
dollar_50 = 50.00
dollar_100 = 100.00
changeTypes = {dollar_100:0,dollar_50:0,dollar_20:0,dollar_10:0,dollar_5:0,dollar_1:0,quarter:0,dime:0,penny:0}
change = amount_paid-cost
if amount_paid < cost:
print('Error: InsufficientFunds')
for changeType in changeTypes:
numAmount = max(0,change//changeType)
change-=numAmount*changeType
changeTypes[changeType] = int(numAmount)
print(changeTypes)
P.S you should make this a function, it shouldn't be too hard.
You could do this good with dictionaries, but without using still there are many ways to go about this, options are endless, heres one idea
def get_bills(change, value):
if change//value > 0:
bills = change//value
change -= bills * value
return bills, change
else:
return 0, change
cost = float(input('Cost: '))
paid = float(input('Amount Paid: '))
while paid < cost:
paid = float(input('Amount Paid: '))
change = paid - cost
hundreds, change, = get_bills(change, 100)
fifties, change, = get_bills(change, 50)
twenties, change = get_bills(change, 20)
tens, change = get_bills(change, 10)
fives, change = get_bills(change, 5)
ones, change = get_bills(change, 1)
quarters, change = get_bills(change, .25)
dimes, change = get_bills(change, .1)
nickels, change = get_bills(change, .05)
pennies = round(change * 100)
print(f"Hundreds: {hundreds}, Fifties: {fifties}, Twenties: {twenties}," +
f" Tens: {tens}, Fives: {fives}, Ones: {ones}, Quarters: {quarters}," +
f" Dimes: {dimes}, Nickels: {nickels}, Pennies: " +
f"{pennies}")
bill = float(input())
paid = float(input())
Available = {100.0:0,50.0:0,20.0:0,10.0:0,5.0:0,1.0:0,0.25:0,0.10:0,0.01:0}
due = paid-bill
for change in sorted(Available,reverse = True):
amt= max(0,due//change)
due-=amt*change
Available[change] = int(amt)
print(Available)
I know this is a late response but maybe it can help someone.
Below is a code for doing exactly what you want. The program iterates through the notes available from largest to smallest and calculates how many times the current note may be used to deduct from the remaining change to be given.
Finally returning a list containing the notes used to reach the sum required.
# Available notes for change
notes = [500, 200, 100, 50, 20, 10]
def change_notes(change, notes):
notes_out = []
for note in notes:
print(f"current note is {note}")
sleep(1)
while change > 0 and note <= change:
if change - note >= 0:
change -= note
notes_out.append(note)
print(f"change is {change}")
sleep(1)
if change == 0:
break
return notes_out

MITx: 6.00.1x Introduction to Computer Science and Programming Using Python

So I'm very new to Python... The problem is as follows:
Write a program to calculate the credit card balance after one year if a person only pays the minimum monthly payment required by the credit card company each month.
My current code is as follows:
month = 1
minimumMonthlyPayment = (balance * monthlyPaymentRate)
totalPaid = 0.0
while month < 13:
print "Month: " + str(month)
print "Minimum Monthly Payment: " + str(round(minimumMonthlyPayment, 2))
balance = (balance - (balance * monthlyPaymentRate)) * (1 + (annualInterestRate/12))
minimumMonthlyPayment = (balance * monthlyPaymentRate)
print "Remaining Balance: " + str(round(balance, 2))
totalPaid += minimumMonthlyPayment
month += 1
print "Total Paid: " + str(round(totalPaid, 2))
print "Remaining Balance: " + str(round(balance, 2))
Here's the correct output:
So all the numbers are identical in both outputs but my Total Paid ends up being 1732.94 instead of the correct amount which is 1775.55. I added the numbers from my output up on a side calculator and it came out to 1775.55 as well. Is there something in my code that's borking this?
Here are the values for the variables that the test code uses:
balance = 4213;
annualInterestRate = 0.2;
monthlyPaymentRate = 0.04;
Great job! Your code is almost perfect. The only mistake is that line 8 needs to run before line 9. You're changing the balance and then using that changed balance to calculate the minimum monthly payment. You need to calculate the minimum monthly payment for each month before you update the balance.
Hope this helps!
balance = 4213
annualInterestRate = 0.2
monthlyPaymentRate = 0.04
totalPaid = 0.0
month = 1
minimumMonthlyPayment = balance * monthlyPaymentRate
while month < 13:
print "Month: " + str(month)
print "Minimum Monthly Payment: " + str(round(minimumMonthlyPayment, 2))
minimumMonthlyPayment = balance * monthlyPaymentRate
balance = (balance - (balance*monthlyPaymentRate))*(1+(annualInterestRate/12))
print "Remaining Balance: " + str(round(balance, 2))
totalPaid += minimumMonthlyPayment
month += 1
print "Total Paid: " + str(round(totalPaid, 2))
print "Remaining Balance: " + str(round(balance, 2))
You are recalculating your balance before calculating your minimumMonthlyPayment rate.
So balance * monthlyPaymentRate comes to a different amount on line 8 and 9 since balance has changed.
If you assign balance * monthlyPaymentRate to a variable before those lines and use it for both calculations it would correct this.

Python-Modulus-Stuck with a coin-for-given-dollar-amount scenario

Specs: Ubuntu 13.04, Python 3.3.1
General Background: total beginner to Python;
Question-specific background: I'm exhausted trying to solve this problem, and I'm aware that, besides its instructional value for learning Python, this problem is boring and does not in any way make this world a better place :-( So I'd be even more grateful if you could share some guidance on this exhausting problem. But really don't want to waste your time if you are not interested in this kind of problems.
What I intended to do: "Calculate the number of basic American coins given a value less than 1 dollar. A penny is worth 1 cent, a nickel is worth 5 cents, a dime is worth 10 cents,
and a quarter is worth 25 cents. It takes 100 cents to make 1 dollar. So given an amount less than 1 dollar (if using floats, convert to integers for this exercise), calculate the number of each type of coin necessary to achieve the amount, maximizing the number of larger denomination coins. For example, given $0.76, or 76 cents, the correct output would be "3 quarters and 1 penny." Output such as "76 pennies" and "2 quarters, 2 dimes, 1 nickel, and 1 penny" are not acceptable."
What I was able to come up with:
penny = 1
nickel = 5
dime = 10
quarter = 25
i = input("Please enter an amount no more than 1 dollar(in cents): ")
i = int(i)
if i > 100:
print ("Please enter an amount equal or less than 100. ")
elif i >= quarter:
quarter_n = i % quarter
i = i - quarter * quarter_n
if i >= dime:
dime_n = i % dime
i = i - dime * dime_n
if i >= nickel:
nickel_n = i % nickel
i = i - nickel * nickel_n
if i >= penny:
penny_n = i % penny
print (quarter_n,"quarters,",dime_n,"dimes",nickel_n,"nickels",penny_n,"pennies")
else:
if i >= penny:
penny_n = i % penny
print (quarter_n,"quarters,",dime_n,"dimes",penny_n,"pennies")
else:
if i >= nickel:
nickel_n = i % nickel
i = i - nickel * nickel_n
if i >= penny:
penny_n = i % penny
print (quarter_n,"quarters,",nickel_n,"nickels",penny_n,"pennies")
else:
if i >= penny:
penny_n = i % penny
print (quarter_n,"quarters,",penny_n,"pennies")
else:
if i >= dime:
dime_n = i % dime
i = i - dime * dime_n
if i >= nickel:
nickel_n = i % nickel
i = i - nickel * nickel_n
if i >= penny:
penny_n = i % penny
print (dime_n,"dimes",nickel_n,"nickels",penny_n,"pennies")
else:
if i >= penny:
penny_n = i % penny
print (dime_n,"dimes",penny_n,"pennies")
else:
if i >= nickel:
nickel_n = i % nickel
i = i - nickel * nickel_n
if i >= penny:
penny_n = i % penny
print (nickel_n,"nickels",penny_n,"pennies")
else:
if i >= penny:
penny_n = i % penny
print (penny_n,"pennies")
This solution, though the best I could come up with, does not work as expected when fed with actual input numbers. And I'm unable to figure out why. Besides, I know that even from sheer size of the code that something is wrong. I searched for similar questions but the closest I got was one that dealt with very difficult math which I couldn't understand.
My question: I know I can't ask for a complete solution because that's down to me to figure it out. I'll appreciate either a) general pointer on the correct line of thinking b) critiques to my current code/line of thinking so that I might be able to improve it.
Thank you for taking the time, even just reading this!
I think your solution may actually be working if you do a "find and replace" for all the mod operators %, switching in integer division //.
Say you have 76 cents and want to find the number of quarters. Using 76 % 25 results in 1 whereas 76 // 25 is 3.
With regard to the code, you should probably be thinking in terms of iterating over the possible coin values rather than a huge if, elif mess.
Try something like this. The only part that may need some explaining is using divmod but its really just a tuple of the integer division, modulo result. You can use that to get the number of coins and the new amount, respectively.
def coins_given(amount):
coins = [(25, 'quarter'), (10, 'dime'), (5, 'nickel'), (1, 'penny')]
answer = {}
for coin_value, coin_name in coins:
if amount >= coin_value:
number_coin, amount = divmod(amount, coin_value)
answer[coin_name] = number_coin
return answer
print coins_given(76)
# {'quarter': 3, 'penny': 1}
i think your algorithm is too complicated,
you don't need all the elifs and the elses
just check with and if and then modidy the remaining amount until you get to zero
something like this
penny = 1
nickel = 5
dime = 10
quarter = 25
q = 0
d = 0
n = 0
p = 0
i = input("Please enter an amount no more than 1 dollar(in cents): ")
i = int(i)
if i>=25:
q = i/quarter
i %= quarter
if i>=10:
d = i/dime
i%=dime
if i>=5:
n = i/nickel
i %= nickel
if i>0:
p = i/penny
i = 0
print "The coins are %i quarters, %i dimes, %i nickels and %i pennys." %(q , d, n, p)
>>>
Please enter an amount no more than 1 dollar(in cents): 99
The coins are 3 quarters, 2 dimes, 0 nickels and 4 pennys.
>>>
Please enter an amount no more than 1 dollar(in cents): 76
The coins are 3 quarters, 0 dimes, 0 nickels and 1 pennys.
dime=10
nickel=5
penny=1
quarter=25
def change(cents):
changeIs = ""
qs = cents/quarter
cents %= quarter
if qs > 0 :
changeIs += str(qs) + " quarter(s)"
ds = cents/dime
cents %= dime
if ds > 0 :
changeIs += " " + str(ds) + " dime(s)"
ns = cents/nickel
cents %= nickel
if ns > 0 :
changeIs += " " + str(ns) + " nickel(s)"
if cents > 0 :
changeIs += " " + str(cents) + " cent(s)"
return changeIs
if __name__ == '__main__':
cents=int(raw_input("Enter the change: "))
print change(cents)

Categories

Resources