2

I am conversting a float to integer in the below code. But , the resultant output is not correct for nickels.

Code:

actual = 25
paid = 26.65
cents = (paid-actual)*100
quarters = int(cents/25)
cents = cents %25
dimes = int(cents/10)
cents = cents %10
nickels = int(cents/5)
print quarters, dimes, nickels,cents
print 5.0/5,int(5.0/5)

Ouput:

6 1 0 5.0
1.0 1

Expected output

6 1 1 5.0
1.0 1

If i explicitly do int(5.0/5) I get 1 , but when the same is done assigned to a variable in my code, I get 0 . I am not sure why. Can someone explain ?

4 Answers 4

6

Floating point numbers are not guaranteed to be spot on the number you expect, they could just be barely off, say 5.0 might actually be 4.999... and since int() truncates/rounds down, you get your error.

Many banks just completely give up on the floating point issue and just work with $1.00 = 100 I would advise you do the same, like this:

actual = 25
paid = 26.65
cents = int(round(paid*100)) #Turns 26.65 into 2665 before you do any float math
dollars = cents / 100
cents %= 100
quarters = cents / 25
cents %= 25
dimes = cents / 10
cents %= 10
nickels = cents / 5
print quarters, dimes, nickels,cents
print 5.0/5,int(5.0/5)

note that this outputs 2 1 1 5 because that's 2 quarters, 1 dime, and 1 nickel = $.65

Typically you want to round as LATE as possible to maintain precision, but when you are working with money, I think working entirely with ints makes the nightmare of floats go away faster.

Also, since you are using 2.6, you will need to cast to int() because round() doesn't return an integer until 3.1

Sign up to request clarification or add additional context in comments.

2 Comments

I'd even avoid 26.65 and go directly for 2500 and 2665.
@LennartRegebro didn't want to change his inputs, but yes I would do something similar
3

Floating point numbers cannot represent all real numbers.

Every time you do anything with floating-point numbers, you are approximating the exact result by the closest thing your floating-point representation can represent. When you write

26.65

Python actually uses

26.64999999999999857891452847979962825775146484375

When you do math with floating point numbers, the result is rounded to the nearest representable number. print truncates floating-point numbers to 12 decimal places, so the small inaccuracies aren't visible, but when you compute

int(cents/5)

cents is actually 4.999999999999858, and cents/5 is 0.9999999999999716, which rounds down to 0.

2 Comments

how can we verify the value of cents? when I have printed it out it shows 5.0
@misguided: print repr(cents). Personally, I feel that the default 12 digits of displayed precision are a mistake. If people want 12 digits, they can get that with string formatting.
2

Other users have explained how floating points are inexact. In your case, consider using Decimal for more precise calculations:

>>> from decimal import Decimal
>>> actual = Decimal('25')
>>> paid = Decimal('26.65')
>>> actual,paid
(Decimal('25'), Decimal('26.65'))
>>> cents = (paid-actual)*100
>>> cents
Decimal('165.00')
>>> quarters = int(cents/25)
>>> cents = cents % 25
>>> dimes = int(cents/10)
>>> cents = cents %10
>>> nickels = int(cents/5)
>>> print quarters, dimes, nickels,cents
6 1 1 5.00
>>> cents
Decimal('5.00')

Take note of the strings for the numbers creating the original actual and paid. They're required.

Comments

1

When you do int(x), it ALWAYS rounds down, meaning if you do int(4.9999) you'll get 4. Consider using int(round(x)) instead

EDIT:

Wait...if you've multiplied by 100, why are you even using floats at all? What do you need the decimals for? Why not just turn cents into an int after you multiply by 100 and then get rid of all of this float nonsense?

4 Comments

int(round(x)) would round up in cases where it shouldn't, using too many coins.
The issue here is in the inacuracy of his floating point numbers. Instead of rounding inside of the type casting, round cents every time you set it. So it becomes cents = round(cents % 25). I just dealt with a similar question yesterday that might help you (stackoverflow.com/questions/17779336/…)
rounding gives the output as 7 1 1 while it should be 6 1 1
Ahh you're right. Wait...if you've multiplied by 100, why are you even using floats at all? What do you need the decimals for? Why not just turn cents into an int after you multiply by 100 and then get rid of all of this float nonsense? (If you take a look at the other question I posted I'm pretty sure that's what we ended up doing)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.