0

I was doing a coding challenge and run into this problem that I have never encounter before. The question ask to return change in the most efficient way. User put in the price, and the amount paid as an array (kinda like giving money to the vending machine)

for some reason, the code doesn't pass the last if block when the remaining change is 0.01

def ChangeMaker(price, payment):
    # Write your code here
    totalPayment=0
    for i in payment:
        totalPayment+=i
    change = totalPayment-price
    coinChange=change-int(change)

    def helper(remain, result):
        holder= result
        newRemain = remain
        if remain>=.25:
            holder[3]+=1
            newRemain-=.25
            return helper(newRemain, holder)
        elif remain>=.10:
            holder[2]+=1
            newRemain -=.10
            return helper(newRemain, holder)
        elif remain>=.5:
            holder[1]+=1
            newRemain -=.05
            return helper(newRemain, holder)
        elif remain>.01 or remain==.01:
            holder[0]+=1
            newRemain -=.01
            return helper(newRemain, holder)
        else:
            return holder;
    return helper(coinChange, [0,0,0,0])

print(ChangeMaker(1.87, [5, .25,.25,.25,.25, 1]))
Prune
  • 76,765
  • 14
  • 60
  • 81
  • You are most likely a victim of floating point imprecision. – gmds Apr 26 '19 at 00:19
  • How do you know it's actually greater than or equal to `0.01`? Floating point is a mess; the logical answer might be `0.01`, but the computed result could easily be `0.009999999999999998` or something. If you're working with money, always use the `decimal` module, and always initialize your `Decimal`s with either `str` or `int`, never use `float`. – ShadowRanger Apr 26 '19 at 00:21
  • Side-note: `remain>.01 or remain==.01` is a strange/slow way to spell `remain >= .01`. – ShadowRanger Apr 26 '19 at 00:22

1 Answers1

0

As @gmds said this is purely a floating point precision issue. Here is a quick solution for calculation money (with only 2 decimal places) by timing every number by 100 then converting them to integer.

def ChangeMaker(price, payment):
    # Write your code here
    totalPayment=int(sum(payment) * 100)
    price = int(price * 100)
    change = totalPayment-price
    coinChange=change % 100

    def helper(remain, result):
        holder= result
        newRemain = remain
        if remain>=25:
            holder[3]+=1
            newRemain-=25
            return helper(newRemain, holder)
        elif remain>=10:
            holder[2]+=1
            newRemain -= 10
            return helper(newRemain, holder)
        elif remain>=5:
            holder[1]+=1
            newRemain -= 5
            return helper(newRemain, holder)
        elif remain >= 1:
            holder[0]+=1
            newRemain -= 1
            return helper(newRemain, holder)
        else:
            return holder
    return helper(coinChange, [0,0,0,0])

print(ChangeMaker(1.87, [5, .25,.25,.25,.25, 1]))
Philip Tzou
  • 5,926
  • 2
  • 18
  • 27