You are viewing cniehaus

Previous Entry | Next Entry

Casting an int to a float in Python 2.6

Taken in Portugal
Moin

Does


%d / %d is %f" % (num1, num2, float(num1)/num2)


have any (dis)advantages over


%d / %d is %f" % (num1, num2, float(num1)/float(num2))


? Both work. If one number is a float both are treated as a float, as far as I know.

Does the first line have any (technical) disadvantages over the second?

Comments

( 22 comments — Leave a comment )
(Anonymous)
Mar. 15th, 2009 10:41 am (UTC)
Hmm i don't think so
I may be a newbie but after compilation it doesn't matter? It will look like the second line after all? Again, i'm a newbie.
cniehaus
Mar. 15th, 2009 11:06 am (UTC)
Re: Hmm i don't think so
Yes, both have the same result. I am just not sure if there is an aspect I just don't know about. Perhaps one should always use the second line for a reason I don't know (I am a Python-n00b myself).
(Anonymous)
Mar. 15th, 2009 12:09 pm (UTC)
Re: Hmm i don't think so
There are technically no disadvantages between the first and the second solution. You can have a look at the (excellent) Python documentation:


Arithmetic conversions¶

When a description of an arithmetic operator below uses the phrase “the numeric arguments are converted to a common type,” the arguments are coerced using the coercion rules listed at Coercion rules. If both arguments are standard numeric types, the following coercions are applied:

* If either argument is a complex number, the other is converted to complex;
* otherwise, if either argument is a floating point number, the other is converted to floating point;
* otherwise, if either argument is a long integer, the other is converted to long integer;
* otherwise, both must be plain integers and no conversion is necessary.

Some additional rules apply for certain operators (e.g., a string left argument to the ‘%’ operator). Extensions can define their own coercions.

As you can see at the second rule, a casting is implicitly executed. This is exactly the same, as the if you write the explicit conversion in your code.

I would prefer the explicit version, as it make more clear, what will happen!
(Anonymous)
Mar. 15th, 2009 01:23 pm (UTC)
Re: Hmm i don't think so
First line is fine.
(Anonymous)
Mar. 15th, 2009 02:21 pm (UTC)
Re: Hmm i don't think so
Well it's not different because it's int to float. If it is float to in it would of course matter!
But float after dividing is a little bit faster:
Try this
import time

timeone = time.time()
for i in range(9999999):
a = float (i / (3))
print time.time() - timeone

and

import time

timeone = time.time()
for i in range(9999999):
a = float (i) / float(3)
print time.time() - timeone

and the second is here around 40% slower.
(Anonymous)
Mar. 15th, 2009 06:21 pm (UTC)
Re: Hmm i don't think so
Converting the value afterwards defeats the purpose
(Anonymous)
Mar. 15th, 2009 11:46 pm (UTC)
Re: Hmm i don't think so
But your first one is performing integer division, so when i is 1, a will become 0. In the second case, when i is 1, a will become 0.3333.

What I would use in this case is:
a = i / 3.0
(Anonymous)
Mar. 16th, 2009 01:41 am (UTC)
Re: Hmm i don't think so
Except in the first case you cast the result of an integer division to an int, whereas in the second case you perform a real float division. For i = 2 for example, float(2/3) is 0.0, and float(2) / float(3) = 0.66666
(Anonymous)
Mar. 15th, 2009 05:11 pm (UTC)
Re: Hmm i don't think so
They're the same in 2.6. In 2.1 however 3/2 was 1 as it would have used integer division.

Rich.

(Anonymous)
Mar. 15th, 2009 12:11 pm (UTC)
Preferred way probably is to use the 'true division' semantics of PEP 238 (http://www.python.org/dev/peps/pep-0238/)

that is:
from __future__ import division

"%d / %d is %f" % (num1, num2, num1/num2)

This has been in Python since 2.2, so maybe the __future__ import is not necessary anymore.
(Anonymous)
Mar. 15th, 2009 01:39 pm (UTC)
equivalent
Python will use float division as soon as one of the operands is a float.
So all versions will work. float(2)/3, 2/float(3) and float(2)/float(3) are equivalent.
In Py 3000 divisions will always result in floating point numbers unless you specify otherwise (thus making 2/3 also equivalent).
Greetings,
Frederik
Einar [myopenid.com]
Mar. 15th, 2009 01:39 pm (UTC)
Why not just using true division?
Why not just using true division?

from __future__ import division

at the start of the import statements will make sure you will always have a float in return.
(Anonymous)
Mar. 15th, 2009 02:00 pm (UTC)
Future
A third option is to add the following line to the top of your module: from __future__ import division This will make all divisions work like expected. Python 3 has this behaviour by default (hence the future reference). If you do this you can use // to get the old behaviour.
(Anonymous)
Mar. 15th, 2009 02:11 pm (UTC)
future
I can't answer your question, I assume you have a good reason for the explicit cast but just in case you don't (or didn't know):
code
>>> from __future__ import division
>>> num1 = 3
>>> num2 = 4.5
>>> print "%d / %d = %f" % (num1, num2, num1/num2)
3 / 4 = 0.666667
/code
(Anonymous)
Mar. 15th, 2009 02:12 pm (UTC)
From Future
If you use "from __future__ import division" you can even do away with float(num1), and just do num1/num2. It will automatically convert it to a float if the division doesn't result in an integer. I always enable it as standard practice, first because it is the only behavior in python 3 so I want to future proof, second because the default behavior is unpredictable (it works differently if the variables are floats than if they are ints), and third because we already have // for integer division.

As for your specific question, I honestly am not sure, but from what I read it is almost always better to avoid forcing a type conversion if possible. Python is supposed to be highly optimized, so it is usually much better than you are at figuring out the best way to do something. It also makes the code cleaner, easier to read, and easier to maintain. This is a general rule rather than an answer to your specific question, though. As an example, imagine 2.6/2. Although I am not sure, I could imagine that keeping it as an int might be faster in this case than forcing it to be a float.
Lee [irukado.org]
Mar. 15th, 2009 02:12 pm (UTC)
According to the Learning Python notes on the division operator(s) in 2.6/3.0 (http://www.rmi.net/~lutz/lp3e-updates-notes-python.html#NX18), division is always float if one of the args are floats. However, in 3.x, / will always use a float, and you use // for (converting to) integer division. Presumably python will optimise // in the case that both operands are ints.
(Anonymous)
Mar. 15th, 2009 02:49 pm (UTC)
AFAIK they are the same. float.__div__ operator will always cast its argument to float.
(Anonymous)
Mar. 15th, 2009 04:34 pm (UTC)
If one of the arguments to '/' is a float, the result will be a float. Therefore, casting only num1 (or only num2) is enough. For code readability, I would prefer the first line.

Note that Python3 has a different syntax for division ('/' always returns a float, and '//' returns an integer).
(Anonymous)
Mar. 15th, 2009 04:40 pm (UTC)
it's the same
$ python
>>> def f1(a,b): return float(a)/b
>>> def f2(a,b): return float(a)/float(b)
>>> def f3(a,b): return a/float(b)
>>> print all(f1(x,y) == f2(x,y) == f3(x,y) for x in xrange(-1000, 1000) for y in xrange(-1000, 1000) if x if y)
True
>>>

also, from http://docs.python.org/library/stdtypes.html#typesnumeric

Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the “narrower” type is widened to that of the other, where plain integer is narrower than long integer is narrower than floating point is narrower than complex. Comparisons between numbers of mixed type use the same rule. [2] The constructors int(), long(), float(), and complex() can be used to produce numbers of a specific type.

at last: I won't call it "casting"... better call them "converting functions"
(Anonymous)
Mar. 15th, 2009 05:01 pm (UTC)
Using

from __future__ import division

you can safely write num1/num2. This is default in Python 3 (int/int -> float).

float(num1)/num2 will result in a float even if num2 is an int.

float(num1)/float(num2) is redundant.
(Anonymous)
Mar. 15th, 2009 05:33 pm (UTC)
casting ints to floats
I'm using Python 2.5, but I'm fairly certain this applies to 2.6 as well.

The first line does have some advantages over the second. They are both produce the same results because if you try an arithmetic operation with dissimilar types they are coerced into a common type, and that is a float if you are dealing with an int and a float. (There's a builtin coerce() function that does the same thing, but I've never found a good use for it.) This is not done in the compilation step tho...if you look at the bytecode you can see:

>>>import dis
>>>dis.dis('float(3)/4')
0 BUILD_TUPLE 28524
3 STORE_GLOBAL 10356 (10356)
6 DELETE_SLICE+1
7 STORE_SLICE+1
8 <47>
9 DELETE_SLICE+2
>>>dis.dis('float(3)/float(4)')
0 BUILD_TUPLE 28524
3 STORE_GLOBAL 10356 (10356)
6 DELETE_SLICE+1
7 STORE_SLICE+1
8 <47>
9 BUILD_TUPLE 28524
12 STORE_GLOBAL 10356 (10356)
15 DELETE_SLICE+2
16 STORE_SLICE+1

so you by doing two explicit conversions you are actually making the interpreter do more work. as for timing...in IPython this time:

In [1]: %timeit float(3)/4
1000000 loops, best of 3: 340 ns per loop

In [2]: %timeit float(3)/float(4)
1000000 loops, best of 3: 534 ns per loop

So seems to me the first expression you wrote is preferable. There are no gotchas (at least that I know about), so you are probably best off trusting in python's coercion rules doing what you want. If nothing else though, this is an example of why Python3's change in the division operator is a good thing.
(Anonymous)
Mar. 16th, 2009 01:17 pm (UTC)
__future__
As a python user I say also to import from __future__

Then / is the normal division, and // is the floor division
( 22 comments — Leave a comment )

Profile

Taken in Portugal
cniehaus
cniehaus

Latest Month

July 2009
S M T W T F S
   1234
567891011
12131415161718
19202122232425
262728293031 

Page Summary

Powered by LiveJournal.com
Designed by Tiffany Chow