Jacques de Hooge
Jacques de Hooge

Reputation: 6990

What's the rationale behind 2.5 // 2.0 returning a float rather than an int in Python 3.x?

What's the rationale behind 2.5 // 2.0 returning a float rather than an int in Python 3.x? If it's an integral value, why not put it in a type int object?

[edit]

I am looking for a justification of the fact that this is so. What were the arguments in making it this way. Haven't been able to find them yet.

[edit2]

The relation with floor is more problematic than the term "floor division" suggests!

floor(3.5 / 5.5) == 0 (int)

whereas

3.5 // 5.5 == 0.0 (float)

Can not yet discern any logic here :(

[edit3]

From PEP238:

In a unified model, the integer 1 should be indistinguishable from the floating point number 1.0 (except for its inexactness), and both should behave the same in all numeric contexts.

All very nice, but a not unimportant library like Numpy complains when offering floats as indices, even if they're integral. So 'indistinguishable' is not reality yet. Spent some time hunting a bug in connection with this. I was very surprise to learn about the true nature of //. And it wasn't that obvious from the docs (for me).

Since I've quite some trust in the design of Python 3.x, I thought I must have missed a very obvious reason to define // in this way. But now I wonder...

Upvotes: 2

Views: 238

Answers (1)

tobias_k
tobias_k

Reputation: 82899

The // operator is covered in PEP 238. First of all, note that it's not "integer division" but "floor division", i.e. it is never claimed that the result would be an integer.

From the section on Semantics of Floor Division:

Floor division will be implemented in all the Python numeric types, and will have the semantics of

a // b == floor(a/b)

except that the result type will be the common type into which a and b are coerced before the operation.

And later:

For floating point inputs, the result is a float. For example:

3.5//2.0 == 1.0

The rationale behind this decision is not explicitly stated (or I could not find it). However, the way it is implemented, it is consistent with the other mathematical operations (emphasis mine):

Specifically, if a and b are of the same type, a//b will be of that type too. If the inputs are of different types, they are first coerced to a common type using the same rules used for all other arithmetic operators.

Also, if the results would be automatically converted to int, that could yield weird and surprising results for very large floating point numbers that are beyond integer precision:

>>> 1e30 // 2.
5e+29
>>> int(1e30 // 2.)
500000000000000009942312419328

Upvotes: 6

Related Questions