Interesting float/int casting in Python


25th of April 2006

Casting is when you convert a variable value from one type to another. This is, in Python, done with functions such as int() or float() or str(). A very common pattern is that you convert a number, currently as a string into a proper number.

Let me exemplify:

 >>> x = '100'
 >>> y = '-90'
 >>> print x + y
 100-90
 >>> print int(x) + int(y)
 10

That was the int() function. There's also another very common one which is float() which does basically the same thing:

 >>> print float(x) + float(y)
 10.0

Today I had to fix a bug might come as a surprise. Allow me to demonstrate:

 >>> x = '100.0'
 >>> print float(x)
 100.0
 >>> print int(float(x))
 100
 >>> print int(x)
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 ValueError: invalid literal for int(): 100.0

As you can see, the int() function can convert floating point numbers to integers just fine but it can't do that and decode it from a string in one statement. A flaw in the design? No, I don't think so. It's just another design decision that you just have to learn. But, is it to explicit? Would it be that bad if the int() function could do both actions in one builtin sweep?

The bug I found was related to a human height input validator that looked something like this:

 def validHeight(cm):
     try:
         cm = int(cm)
         return 100 <= cm <= 250
     except ValueError:
         return False

 >>> validHeight(190)
 True
 >>> validHeight('190')
 True
 >>> validHeight('')
 False
 >>> validHeight('190.0')
 False # WHAT?!

You see, our system saves all values like this in the database as REAL (floating point decimal values) and when you return to the Height form it prints "190.0" as the default prefilled value in the input box. In the database it's a valid and correct value. The validHeight() function had to be rewritten to this:

 def validHeight(cm):
     try:
         cm = float(cm)
         return 100 <= cm <= 250
     except ValueError:
         return False

 >>> validHeight(190)
 True
 >>> validHeight('190')
 True
 >>> validHeight('')
 False
 >>> validHeight('190.0')
 True

Geez! What a long boring story this became. Just remember, float() is sometimes better than int(). In some cases you might have to use both.



Comment

Show all 13 comments
 
Name:
Email:
hide my email address.

Your email address will be encoded to prevent email-extraction spiders from reading it so you won't get spammed if you decide to show your email address.