Reputation: 2346
This little thing has been driving me crazy for the past couple of hours.
Here is my code. I noticed the problem when I used int()
to round down some numbers. You can see I am printing the float and integer answers side by side for comparison.
class Payment:
def __init__(self):
self.coins = [0.25, 0.5, 1, 3, 15, 75]
def get_change(self, price, payment):
change = (payment - price) * 100.0
self.calculate_change(change)
def calculate_change(self, change):
for coin in self.coins:
print change / coin, int(change / coin)
And in my Main I have:
from Temp import Payment
t = Payment()
t.get_change(2.0, 2.80)
From the Main input the value of change
happens to be 80 and is passed into calculate_change
. Now, have a look at the output
320.0 319
160.0 159
80.0 79
26.6666666667 26
5.33333333333 5
1.06666666667 1
The rounded values are off by 1. That's odd.
But if I just call the calculate_change
function in Main like so:
t.calculate_change(80)
I get what is expected:
320.0 320
160.0 160
80 80
26 26
5 5
1 1
So the problem lies somewhere in the get_change
function. What is it about this line that causes the problem?
change = (payment - price) * 100.0
Upvotes: 0
Views: 583
Reputation: 59671
The problem is that floating point numbers are never represented exactly.
The calculation change = (payment - price) * 100.0
will not give you 80
exactly but 79.9999999
or 80.00000001
.
When you use int
on the former, you are just chopping off everything after the decimal and getting 79
.
The solution is to never use inaccurate data types such as float to represent money. Use whole numbers, so instead of everything in dollars like 2.80
, use cents 280
. Only when you are ready to present the value to the user do you convert to cents to a dollar representation.
Alternatively, you could use something like Python's decimal
class, which can represent decimal numbers with a much higher accuracy at the cost of speed, and a little extra code required each time you work with a number.
Upvotes: 1