pythonpython-3.xfloating-pointfloor-division

python 3 floor division doesn't always result in an int


When using floor division in python3 (and probably also python2 with import __future__):

>>> 2//2
1

the output is an integer as expected. But as soon as one operand is a float, you get a float as result

>>> 2.0//2.0
1.0
>>> 2.0//2
1.0
>>> 2//2.0
1.0

I guess this is intended, but actually I don't understand, why it is supposed to be like this. What is the design concept of using a not previously determined data type as a result of an operation that always yields an integer?

The best a really extensive search gave me (from PEP 238)

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.

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.

In particular:

- if a and b are both ints or longs, the result has the same type and value as
  for classic division on these types (including the case of mixed input types;
  `int//long` and `long//int` will both return a long).
- For floating point inputs, the result is a float.
  For example:  `3.5//2.0 == 1.0`
- For complex numbers, // raises an exception, since floor() of a   complex number is not allowed.  
- For user-defined classes and extension types, all semantics are up  to the implementation of the class or type.

But this still doesn't explain WHY the behavior is implemented like this.


Solution

  • One possible advantage can be the following: If the inputs of an operation are floats, then usually the most useful output type is a float, because the program is doing floating point calculations. Similarly, if the inputs of an operation are integers (ints or longs), then usually the most useful output type is an integer.

    A related surprising data point:

    >>> str(int(123e300 // 10.0))
    '12300000000000000348405169443457756499452463917650245579212965288916278422109198944984236481408634018703901759913201583616648277756338685989513894763895354330869046350917957229381143786183918719192956157930593465276658607709014541611368487360619735051905095032755082564499801643679232993692080863707136'
    

    It's surprising, because it's natural to expect lots of 0s at the end. You get other digits because of the limited precision of the float type.

    So by returning a float, // indicates that the output can be inaccurate.