I tried out one of the "Projects for the Beginner" ideas: the change calculator. Basically, you tell it how much the purchased item was, and how much the customer paid. Then it tells you the change due, and the most efficient combination of bills and coins to pay it.

However, I'm getting some odd problems. Take this one, for example:

Cost of item: 499.99
Money paid:   500
Change: $0.00999999999999
100's: 0
 50's: 0
 20's: 0
 10's: 0
  5's: 0
  1's: 0
  Q's: 0
  D's: 0
  N's: 0
  P's: 0

Merely a penny is due, but it seems to think that 500 - 499.99 is 0.0099999999? Another example has the same problem:

Cost of item: 8.98
Money paid:   9
Change: $0.02
100's: 0
 50's: 0
 20's: 0
 10's: 0
  5's: 0
  1's: 0
  Q's: 0
  D's: 0
  N's: 0
  P's: 1

Can anyone help me fix this? Here is the source:

# change_calc.py

# dictionary storing the amount of each bill/coin needed
m_d = {100: 0, 50: 0, 20: 0, 10: 0, 5: 0, 1: 0, 0.25: 0, 0.1: 0, 0.05: 0, 0.01: 0}
# list of possible bills/coins, really only used in the for loop later on
m_l = [100, 50, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01]
cost = input("Cost of item: ")
paid = input("Money paid:   ")
if paid < cost:
    print "You have not paid enough"
else:
    change = paid - cost
    print "Change: $" + str(change)
    for i in m_l:
        while change >= i:
            m_d[i] += 1
            change -= i

    print "100's:",m_d[100]
    print " 50's:",m_d[50]
    print " 20's:",m_d[20]
    print " 10's:",m_d[10]
    print "  5's:",m_d[5]
    print "  1's:",m_d[1]
    print "  Q's:",m_d[0.25]
    print "  D's:",m_d[0.1]
    print "  N's:",m_d[0.05]
    print "  P's:",m_d[0.01]

python is a little funky when it comes to certain number calculations. try rounding your answer:

print round(500-499.99,2)

this will tell python to get to original answer (0.00999999999999
), and round it to the second decimal (the second argument in round() is the number of decimals to round to) which should give us:

0.01

hope that helps!

I'm actually fairly new with Python, but I have some experience with other languages, and in alot of languages, they won't keep floats exactly as we want them too. Try multiplying everything by 100 until you need to display it to the user. So 50 cents would be 50 instead of .5, etc.

Also, you might want to make sure you are always dealing withe floats:

>>> float(499.99)
499.99000000000001
>>> float(500) - float(499.99)
0.0099999999999909051
>>> round(float(500) - float(499.99),2)
0.01
>>> type(499.99)
<type 'float'>
>>> type(500)
<type 'int'>

And round is definitely a must.

To take care of the ever present binary roundoff error that is associated with floating point numbers (most any computer language) do this:

# compensate for the binary roundoff error
        while change >= (m - 0.001):

In the matter of fact you can streamline your code to this:

# change_calc.py
# calculate the change given to a customer using the least
# amount of bills and coins (US currency)

#cost = input("Cost of item: ")
#paid = input("Money paid:   ")
# for testing ...
cost = 262.99
paid = 500.00

# dictionary storing the amount of each bill/coin needed
m_d = {100: 0, 50: 0, 20: 0, 10: 0, 5: 0, 1: 0, 0.25: 0, 0.1: 0, 0.05: 0, 0.01: 0}

if paid < cost:
    print "You have not paid enough"
else:
    # round off to the penny
    change = round((paid - cost), 2)
    print "Change: $" + str(change)
    for m in sorted(m_d, reverse=True):
        # compensate for the binary roundoff error
        while change >= (m - 0.001):
            m_d[m] += 1
            change -= m

    # print the currency options
    print "100's:",m_d[100]
    print " 50's:",m_d[50]
    print " 20's:",m_d[20]
    print " 10's:",m_d[10]
    print "  5's:",m_d[5]
    print "  1's:",m_d[1]
    print "  Q's:",m_d[0.25]
    print "  D's:",m_d[0.1]
    print "  N's:",m_d[0.05]
    print "  P's:",m_d[0.01]

Note, it is the == in >= that will cause the problem with floating point values.

Thank you, everyone! But I have a question for you, sneekula. While I understand why you changed while change >= m: to while change >= (m - 0.001): , does it actually help at all after you've rounded the change variable up to the second decimal place? Or is there a possibility of it dropping back down to the lower places? I've tested it with just the rounding, and it seems to work fine.

And thanks for showing me that I can use the dictionary in the for loop. That's a lot of help :)

The very test numbers I gave you wont work with just rounding! It will miss the one penny change.

Whoops, serves me right for not thoroughly testing. You're right.

But why does it still happen if we've rounded it off?

This article has been dead for over six months. Start a new discussion instead.