Interesting float/int casting in Python

25 April 2006   15 comments   Python

Powered by Fusion×

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.

Comments

Steve Holden
Of course normally you would define a function that used float() and int() along with exception handling to do exactly what you needed, just like you did with ValidHeight. The real question (no pun intended) is why you are storing them in the database as floating point numbers when you are validating them as integers. It's that discrepancy that gives rise to the problem in the first place.
Peter Bengtsson
The reason we stored them as real was because in this particular application we reuse the same sql table for storing the answers to all questions in a complex questionnaire and part of it was a slightly off-topic question about the users height and weight.
Ian Bicking
I think I saw something in the py3k list about distinguishing truncation from coercion, which is basically the problem you are having.
Anonymous
why not use:

cm = eval(cm)

or even:

cm = int(eval(cm))
Carl Friedrich Bolz
because then some mean person could give you some input like "2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** (2 ** 2)))))))))))))))))))" on the webpage, taking loads of CPU on your server. Or even worse, try to delete some files. This probably works, because the strings that are validated seem to be user-provided.
drew
"casting" usually means using an object of one type as another. In C, (char *)voidPtr doesn't convert anything, and it doesn't make a new object. It just uses voidPtr as a char*. I recommend saying 'convert' (like you did most of the time) and leaving the term 'cast' for times when an object is forced to be interpreted as something else (which isn't happening in your demos).
Peter Bengtsson
Thanks! Interesting. Cast is like when a man dresses up like a drag queen. Doesn't make him a woman.
Converting is like a man having a sex change operation then I guess.
:)
Robert
What a fantastic analogy! Thanks!
mypalmike
Casting does mean converting. In both C and Python, casting from float to int is very much a conversion. It takes the original fp number, which is generally represented internally as an IEEE 754 floating point value, and converts it to an twos completment integer representing the floor of the value. The new value has a completely different representation than the original. In other words, it is a different object.

Your example of casting pointers doesn't modify anything because a pointer is a pointer, so no underlying representation needs to be changed for the semantics of conversion to take place.
FutureNerd
Casting in C (or C++ or Java) is that (int) x syntax. It sometimes means converting, sometimes means reinterpreting the bytes, sometimes both! E.g., in C:
<pre>
char x = -1;
long y = (unsigned char) x; // y = 255
long z = (unsigned short) x; // z = 65535 (!)</pre>

The Python int(x) syntax more clearly implies "convert" to my eyes.
Nakul
Hi,
I m trying to save the values from the array to the text file in Python. when i give print command to display the array, there is no problem... but when i try to add the values from the array to the text file it is doing nothing..
How to do type casting here..
my code is.

#--code start----------------------------
print 'List values are : ', List[0], List[1],List[2],List[3],List[4]
#--------------------------------------
f=open('temp.txt','w')
f.write(List[0])
f.close()
#--code ends-----------------------------

Note:- I dont know which kind of array is this
So please help me to solve this problem

Regards
Nakul
Peter Bengtsson
Replace
f.write(List[0])
with
f.write(str(List[0]))
Moe
Hi hows it going?
im trying to open a note pad file using python, the commands i use , load the program but when i choose which ever questionare it doesnt load it can u please let me know the problem? because i got a mid term in 5 days thnx alot the code is the following:
def IQ():
x=0
while x!=10:
score =0
myfile= open('IQ.txt', 'r')
question = myfile.readline()
answer1 = myfile.readline()
answer2 = myfile.readline()
answer3 = myfile.readline()
answer4 = myfile.readline()
correct = myfile.readline()
explanation = myfile.readline()
points=float(myfile.readline())
print question
print "1-"+ answer1
print "2-"+ answer2
print "3-"+ answer3
print "4-"+ answer4
answer=raw_input("what's your answer?")
answer=answer.rstrip()
x=x+1
if answer== correct[0]:
print"\nRight",
score+=points
else:
print"\nWrong",
print explanation
print "score:",score,"\n\n"
def Random():
x=0
while x!=10:
score =0
myfile= open('Random.txt', 'r')
question = myfile.readline()
answer1 = myfile.readline()
answer2 = myfile.readline()
answer3 = myfile.readline()
answer4 = myfile.readline()
correct = myfile.readline()
explanation = myfile.readline()
points=float(myfile.readline())
print question
print "1-"+ answer1
print "2-"+ answer2
print "3-"+ answer3
print "4-"+ answer4
answer=raw_input("what's your answer?")
answer=answer.rstrip()
x=x+1
if answer== correct[0]:
print"\nRight",
score+=points
else:
print"\nWrong",
print explanation
print "score:",score,"\n\n"

total=0
while total==0:
print "1- IQ"
print "2- Random"
choice=(raw_input("which game you wana play:"))
try:
choice=int(choice)
if choice==1:
IQ()
total=total+1
if choice==2:
Random()
total=total+1
else:
print"you should enter either 1 or 2"
total=0
except:
print "you should enter a number"
total=0
Graham Jones
Good explanation - I have just discovered to my cost that the same 'feature' exists now, and is not exactly well documented!

Thanks
CircuitDude
Thank you this little ice breaker on python casting is superb!
Thank you for posting a comment

Your email will never ever be published


Related posts

Previous:
Best bicycle locks 22 April 2006
Next:
Helpdeskshow - a quick review 26 April 2006
Related by keywords:
isInt() JavaScript function 22 May 2006
Sorting mixed type lists in Python 3 18 January 2014
Comparing REAL values in PostgreSQL 07 February 2007
Calculator in Python for dummies 17 December 2007
django-html-validator 20 October 2014
Case insensitive list remove call 10 April 2006
C++ templates or not 18 February 2004
Robots.txt Validator 24 January 2004