1

I wrote a simple change calculator in Python for practice, and I've run into a problem. Here's my code:

amounts = (100, 50, 20, 10, 5, 2, 1, 0.25, 0.10, 0.05, 0.01)
def get_change(full_amount): 
    final_change = []
    for amount in amounts:
        number = 0 
        while full_amount >= amount:
            if (full_amount < 0.50 and full_amount > 0.10 and amount == 0.25): break 
            number += 1
            full_amount -= amount
        final_change.append(number)
    return final_change

Let's say I enter 2.40. It goes from 2.40, to 0.40 (a toonie), and then it should go, do to if (full_amount < 0.50 and full_amount > 0.10 and amount == 0.25): break it will skip 0.25 and finish off with four dimes. However, in reality, it ends up with 3 dimes, one nickel, and only four pennies. The problem seems to arise when the remaining amount equals the amount being tested (0.10 cents remaining and 0.10 cents as the amount - and same with the nickel)

Tyler Sebastian
  • 9,067
  • 6
  • 39
  • 62
  • `(full_amount < 0.50 and full_amount > 0.10 and amount == 0.25)` - why do the first two checks? just do `amount == 0.25`. If either of the first two fail, the last check will too - so don't do them – Gareth Latty Sep 18 '13 at 17:46
  • `1.4 - 1 == 0.3999999999999999` – Josh Lee Sep 18 '13 at 17:50

2 Answers2

2

The answer here is that you should not represent indivisible values as floats. Represent everything in cents.

The reason that is the solution is that floats cannot precisely represent all decimals. Accordingly, division by different amounts will not do what you want. Instead, you need to divide integral amounts, and work appropriately with any remainders that occur.

In general, equality checks on floats are also dangerous for that reason: you instead need to decide what difference is "equal enough" and test for that.

Marcin
  • 48,559
  • 18
  • 128
  • 201
1

Multiply everything by 100 to get rid of the decimals. So a dime should be ten cents, a dollar 100 cents and so on. Since floats aren't perfect representations of a number you shoudn't do any equal checkes on them or doubles.

Vulcronos
  • 3,428
  • 3
  • 16
  • 24