I'm learning Python(2.7) at the moment, and an exercise says to write a program which counts how many coins you need to pay a specific sum. My solution is this:
sum = input("Bitte gebe einen Euro Betrag ein: ")
coins = []
euro = [20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01]
for i in euro:
while sum >= i:
sum -= i
coins.append(i)
print coins
This is nearly working, but when I input eg 17,79 it gives me the coins for 17,78.
Bitte gebe einen Euro Betrag ein: 17.79
[10, 5, 2, 0.5, 0.2, 0.05, 0.02, 0.01]
Why? Has this something to do with round?
For currency calculations it's best to avoid float
type if you can, because of accumulating rounding errors. You can do it in a way similar to this:
amount= input("Bitte gib einen Euro Betrag ein: ")
coins = []
cents = [2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1]
amount = int(float(amount) * 100)
for cent in cents:
while amount >= cent:
amount -= cent
coins.append(cent)
print [coin / 100.0 for coin in coins]
I've also changed the variable name from sum
to amount
- sum
will shadow the sum
built-in function.
Result:
Bitte gebe einen Euro Betrag ein: 17.79
[10.0, 5.0, 2.0, 0.5, 0.2, 0.05, 0.02, 0.02]
Alternatively, you can implement this without inner while
loop, like this:
for cent in cents:
n = int(math.floor(amount / cent))
amount -= n * cent
coins += [cent] * n
It's possible to exit loop earlier ( if not amount: break
) and avoid unnecessary operations ( if not n: continue
), but I omitted these guards for readability.
Another possible alternative is to use the decimal
data type.
It has. If after executing the code you check the 'sum' value, you get something like 0,009999999999999133, which IS smaller than the smallest coin.
My suggestion? Do everything in cents!
sum = int(input("Your text") * 100)
cents = [2000,1000,500,200,100,50,20,10,5,2,1]
coins = []
for i in euro:
while True:
if i <= sum:
coins.append(i)
sum -= i
else:
break
for i in range(len(coins)):
coins[i] /= 100
print(coins)
This is a problem related to float
accuracy. After the calculation, I get:
sum == 0.009999999999999133
ie slightly less than one Euro cent (note, you shouldn't call it sum
because then you shadow the built-in sum
function and can't use eg sum(coins)
to get the total). You can fix this with a tolerance approach, replacing
while sum >= i:
with
while (sum - i) > -0.001: # allow for slight inaccuracy
Similarly, it is best to compare floats using a tolerance, instead of:
if a == b:
use
if abs(a - b) < tolerance:
Indeed, as was pointed out, this seems to be a rounding problem, since the algorithm (for this set of coins!) is correct. If you store the coins as integers in cents, the correct solution is calculated:
s = input("Bitte gebe einen Euro-Cent Betrag ein: ")
coins = []
euro = [2000,1000,500,200,100,50,20,10,5,2,1]
for i in euro:
while s >= i:
s -= i
coins.append(i)
print coins
Output:
Bitte gebe einen Euro-Cent Betrag ein: 1779
[1000, 500, 200, 50, 20, 5, 2, 2]
Btw, I would recommend not to use sum
as a variable name since it is the name of a built-in function.
@BartoszKP pointed out that it's best to avoid using float
and because you might end up with some nasty decimals that you won't like. So you might want to use round
, with minimal changes to your code, you can do this:
sum = input("Bitte gebe einen Euro Betrag ein: ")
coins = []
euro = [20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01]
for i in euro:
while sum >= i:
sum -= round(i,2)
coins.append(i)
if sum > 0:
coins.append(round(sum,2))
print coins
[out:]
Bitte gebe einen Euro Betrag ein: 19.99
[10, 5, 2, 2, 0.5, 0.2, 0.2, 0.05, 0.02, 0.01, 0.01]
But this is NOT the optimal solution since since you would want this instead ;)
Bitte gebe einen Euro Betrag ein: 19.99
[10, 5, 2, 2, 0.5, 0.2, 0.2, 0.05, 0.02, 0.02]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.