TAGS :Viewed: 17 - Published at: a few seconds ago

[ '//' operator in Python not returning correct solution ]

I'm working on a change calculator script for my CS course. Code is below:

# Set up our money variables
centValueOfTenDollarBill = 1000
centValueOfFiveDollarBill = 500
centValueOfToonie = 200
centValueOfLoonie = 100
centValueOfQuarter = 25
centValueOfDime = 10
centValueOfNickel = 5

# Set up our variables
purchaseTotal = input("Enter purchase total: ")  # Purchase costs $12.50
moneyPaid = input("Enter money paid:  ")      # Customer gives cashier $20.00

# Figure out the change
change = moneyPaid - purchaseTotal

# Echo input data to user
print("""The total of the purchase is $%0.2f.
The customer paid $%0.2f.
The cashier gives $%0.2f back to the customer in the following fashion: """ %(purchaseTotal, moneyPaid, change))

#Convert dollars into cents to facilitate the computation
purchaseTotalInCents = purchaseTotal * 100
moneyPaidInCents = moneyPaid * 100
changeInCents = change * 100

# Determine # of $10 to be given back as part of the change
numberOfTenDollarBills = changeInCents // centValueOfTenDollarBill
changeInCents = changeInCents - (centValueOfTenDollarBill * numberOfTenDollarBills)

# Determine # of $5 to be given back as part of the change
numberOfFiveDollarBills = changeInCents // centValueOfFiveDollarBill
changeInCents -= (centValueOfFiveDollarBill * numberOfFiveDollarBills)

# Determine # of $2 (toonies) to be given back as part of the change
numberOfToonieCoins = changeInCents // centValueOfToonie
changeInCents -= (centValueOfToonie * numberOfToonieCoins)

# Determine # of $1 (loonies) to be given back as part of the change
numberOfLoonieCoins = changeInCents // centValueOfLoonie
changeInCents -= (centValueOfLoonie * numberOfLoonieCoins)

# Determine # of $0.25 (quarters) to be given back as part of the change
numberOfQuarterCoins = changeInCents // centValueOfQuarter
changeInCents -= (centValueOfQuarter * numberOfQuarterCoins)

# Determine # of $0.10 (dimes) to be given back as part of the change
numberOfDimeCoins = changeInCents // centValueOfDime  #<--- PROBLEM HERE IF DIMES ARE TWO
print (numberOfDimeCoins)
changeInCents -= (centValueOfDime * numberOfDimeCoins)

# At this point, changeInCents can either be
# 5 -> 1 x $0.05 (nickels) or
# 0 -> 0 x $0.05 (nickels)
numberOfNickelCoins = changeInCents // centValueOfNickel

# Output the result: change cashier needs to give back to customer
print("\t%i x $10.00" %numberOfTenDollarBills)
print("\t%i x $ 5.00" %numberOfFiveDollarBills)
print("\t%i x $ 2.00" %numberOfToonieCoins)
print("\t%i x $ 1.00" %numberOfLoonieCoins)
print("\t%i x $ 0.25" %numberOfQuarterCoins)
print("\t%i x $ 0.10" %numberOfDimeCoins)
print("\t%i x $ 0.05" %numberOfNickelCoins)

# Indicates the end of execution
print("----\n")

All that's wrong (at least from what I can see) is that if the program is supposed to give back two dimes, it gives back one dime and one nickel which short changes the customer five cents. If it's supposed to give back one dime, then there's no issue.

Example: Say a customer paid $20 for a $13.30 item. The change is $6.70.

numberOfDimeCoins = changeInCents // centValueOfDime

This line above should be the same as 2.0 = 20.0//10.0 but instead it's returning 1.0.

If you paid $20 for anything where one dime is required to give back, everything is correct, like $13.20, $13.90, or $13.75 items.

Here's some example outputs below:

Erics-MacBook-Pro:Desktop eric$ python change.py
Enter purchase total: 13.75
Enter money paid:  20
The total of the purchase is $13.75.
The customer paid $20.00.
The cashier gives $6.25 back to the customer in the following fashion: 
    0 x $10.00
    1 x $ 5.00
    0 x $ 2.00
    1 x $ 1.00
    1 x $ 0.25
    0 x $ 0.10
    0 x $ 0.05
----

Erics-MacBook-Pro:Desktop eric$ python change.py
Enter purchase total: 12.8
Enter money paid:  20
The total of the purchase is $12.80.
The customer paid $20.00.
The cashier gives $7.20 back to the customer in the following fashion: 
    0 x $10.00
    1 x $ 5.00
    1 x $ 2.00
    0 x $ 1.00
    0 x $ 0.25
    1 x $ 0.10
    1 x $ 0.05
----

Is there something that I'm missing or did wrong?

Using Python 2.7.

Answer 1


If you inspect the variables, you will see the problem

>>> changeInCents
19.999999999999886
>>> centValueOfDime
10

This is due to the limited precision of floating point.

You should convert the inital values to cents. eg.

numberspurchaseTotalInCents = int(purchaseTotal * 100)
moneyPaidInCents = int(moneyPaid * 100)
changeInCents = moneyPaidInCents - numberspurchaseTotalInCents

Also check out the builtin divmod() function

Answer 2


This is because of floating point precision problem. Try this:

purchaseTotal = 13.3
moneyPaid = 20

change = moneyPaid - purchaseTotal
print(repr(change))  # 6.699999999999999

You probably expect change to be 0.7, but in fact it's a number very close to 0.7, but not precisely. In the end, changeInCents gets a number you expect to be 20.0, but actually a little bit smaller.

Answer 3


I was trying to debug your code, but the other mates have figured it out already. You have a problem with how the numbers are stored following IEEE 754 standard (you can know more about it here).

My recommendation for you is to work with decimal (read here)

It is pretty straight forward,

#import and set precision
from decimal import *
getcontext().prec = **x** #you decide it
a = Decimal(10)
b = Decimal(0.9)
print a-b

Read the documentation, it allows you to set a lot of relevant issues on how to round numbers.