Home > Mobile >  Program returning dictionary with coins for change not recognizing 0.01//0.01 as being 1.0
Program returning dictionary with coins for change not recognizing 0.01//0.01 as being 1.0

Time:11-29

This code outputs a dictionary containing the number of coins of each type necessary to reach a certain change, while using the least coins possible.

def change(money):
    res = {}
    coin = 2.0
    while coin>=0.01:
        parcel = money // coin
        res[coin] = int(parcel)
        money -= parcel * coin
        if coin not in (0.5, 0.05):
            coin = coin/2
        else:
            if coin == 0.5:
                coin = 0.2
            else:
                coin  = 0.02
    return res

when executing the function for 7.71 it returns the following:

{2.0: 3, 1.0: 1, 0.5: 1, 0.2: 1, 0.1: 0, 0.05: 0, 0.02: 0, 0.01: 0}

how come it uses 0 coins of 0.01?

CodePudding user response:

As others have stated, it's because of floating-point rounding errors.

A standard workaround is to represent monetary amounts as integer numbers of the smallest unit (usually the cent) instead of as a float number of dollars/euros/pounds/whatever.

Here's an alternative implementation of your function that uses integer arithmetic internally, and only uses float for the input and final output (dict keys).

It also specifies the denominations in a list “constant” instead of in the code. This lets you easily adapt it to other coinage systems, like the US dollar's [100, 25, 10, 5, 1]. (We technically have a half-dollar in circulation, but it's rarely used.)

# Assuming you're using Euro coins here.
DENOMINATIONS = [200, 100, 50, 20, 10, 5, 2, 1]

def change(money):
    res = {}
    cents = round(money * 100)
    for coin in DENOMINATIONS:
        parcel, cents = divmod(cents, coin)
        res[coin / 100] = parcel
    return res

Sample function call:

>>> change(7.71)
{2.0: 3, 1.0: 1, 0.5: 1, 0.2: 1, 0.1: 0, 0.05: 0, 0.02: 0, 0.01: 1}

CodePudding user response:

The problem is in float rounding. E. g. 0.71 - 0.5 = 0.20999999999999996. Use round function.

def change(money):
    res = {}
    coin = 2.0
    while coin>=0.01:
        parcel = money // coin
        res[coin] = int(parcel)
        print(parcel, money, coin, parcel*coin)
        money = round(money - parcel * coin, 2)
        if coin not in (0.5, 0.05):
            coin = coin/2
        else:
            if coin == 0.5:
                coin = 0.2
            else:
                coin  = 0.02
    return res

print(change(7.71))

Result

{2.0: 3, 1.0: 1, 0.5: 1, 0.2: 1, 0.1: 0, 0.05: 0, 0.02: 0, 0.01: 1}
  • Related