Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change calculator only works if one type of coin needed

I'm currently trying to learn python and have been going through beginner projects on /r/learnpython. My idea for the change calculator project was to create a dictionary with keys 'quarter', 'dime', 'nickel', and 'penny', each with values initialized to 0. My code, shown below, appears to only work when the change I input only requires one type of coin, i.e. 0.75 --> 3 quarters, 0.1 --> 1 dime, etc.

 change_map = {
    'quarter' : 0,
    'dime' : 0,
    'nickel' : 0,
    'penny' : 0
}

def calculator(change):
    while change > 0:
        if change >= 0.25:
            change -= 0.25
            change_map['quarter'] += 1
        elif change < 0.25 and change >= 0.10:
            change -= 0.10
            change_map['dime'] += 1
        elif change < 0.10 and change >= 0.05:
            change -= 0.05
            change_map['nickel'] += 1
        elif change < 0.05 and change >= 0.01:
            change -= 0.01
            change_map['penny'] += 1
    print "You need the following: "
    print change_map

change = raw_input("Please enter amount of change: ")
change = float(change)
calculator(change)
like image 309
Alexander Smith Avatar asked Mar 07 '23 04:03

Alexander Smith


1 Answers

Floating point arithmetic error

Your error is due to float arithmetic error. Here is what happens when you input a value such as 0.26.

change = 0.26
change  -= 0.25
change  -= 0.01
print (change) # 8.673617379884035e-18

Since the last value of change is above 0 but below 0.01, you enter an infinite loop.

How to fix it

One way to fix this is to rely on exact arithmetic by using int instead of float to represent discrete values such as currencies. This means making your base unit the cent instead of the dollar.

change_map = {
    'quarter' : 0,
    'dime' : 0,
    'nickel' : 0,
    'penny' : 0
}

def calculator(change):
    while change > 0:
        if change >= 25:
            change -= 25
            change_map['quarter'] += 1
        elif change >= 10:
            change -= 10
            change_map['dime'] += 1
        elif change >= 5:
            change -= 5
            change_map['nickel'] += 1
        else:
            change -= 1
            change_map['penny'] += 1

    print ("You need the following: ")
    print (change_map)

change = raw_input("Please enter amount of change: ")

# Here we convert the decimal value input by the user to cents
change = int(float(change) * 100)

calculator(change)

Example:

Please enter amount of change: 0.26
You need the following: 
{'quarter': 1, 'dime': 0, 'nickel': 0, 'penny': 1}

Improvements

On a side note, you can improve your solution by using a dict of values and names for coins. In particular, this allows you to extend your program by updating the dict instead of having to add a new if-statement.

Here is an example that adds in the possibility to return a dollar as change.

value_map = {
    100: 'dollar',
    25: 'quarter',
    10: 'dime',
    5: 'nickel',
    1: 'penny'
}

def calculator(change):
    change_map = {}

    for value in sorted(value_map, reverse=True):
        coin = value_map[value]
        change_map[coin], change = divmod(change, value)

    print ("You need the following: ")
    print (change_map)

change = raw_input("Please enter amount of change: ")

change = int(float(change) * 100)

calculator(change)
like image 97
Olivier Melançon Avatar answered Mar 18 '23 21:03

Olivier Melançon