What is the reason for difference between integer division and float to int conversion in python?

PythonPython 3.xInteger Division

Python Problem Overview


I have recently noticed that int() rounds a float towards 0, while integer division rounds a float towards its floor.

for instance:

-7 // 2 == -4
int(-7/2) == -3

I have read the documentation which specifies: > class int(x, base=10) > > Return an integer object constructed from a number or string x, or return 0 if no arguments are >given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero.

and: >floor division > >Mathematical division that rounds down to nearest integer. The floor division operator is //. For example, the expression 11 // 4 evaluates to 2 in contrast to the 2.75 returned by float true division. Note that (-11) // 4 is -3 because that is -2.75 rounded downward. See PEP 238.

But it seems illogical for me that 2 similar operations (float division to integer) should return different results.

Is there any motivation for the differences between the functions?

Python Solutions


Solution 1 - Python

Consistency.

You'll need to follow some very basic and seemingly irrelevant explanations to understand it.

In school you have learned division with a remainder. And you have done calculations like this:

8 ÷ 4 = 2 R 0
7 ÷ 4 = 1 R 3
6 ÷ 4 = 1 R 2
5 ÷ 4 = 1 R 1
4 ÷ 4 = 1 R 0
3 ÷ 4 = 0 R 3
2 ÷ 4 = 0 R 2
1 ÷ 4 = 0 R 1
0 ÷ 4 = 0 R 0
        ^------ This is the result of x // 4
            ^-- This is the result of x % 4 (modulo)

Later, you have learned divisions for real numbers:

8 ÷ 4 = 2.0
7 ÷ 4 = 1.75
6 ÷ 4 = 1.5
5 ÷ 4 = 1.25
4 ÷ 4 = 1.0
3 ÷ 4 = 0.75
2 ÷ 4 = 0.5
1 ÷ 4 = 0.25
0 ÷ 4 = 0.0
        ^--- Note that the number in front of the . is int(x/4)

Until this point, you might believe that x // 4 and int(x/4) always give the same result. That's your current understanding of the situation.

However, have a look what happens in the integer division: the number behind R cycles from 3, 2, 1 to 0 and then restarts: 3, 2, 1, 0. The number in front of the R decreses every 4th step.

So, how will it go on?

 8 ÷ 4 =  2 R 0
 7 ÷ 4 =  1 R 3
 6 ÷ 4 =  1 R 2
 5 ÷ 4 =  1 R 1
 4 ÷ 4 =  1 R 0
 3 ÷ 4 =  0 R 3
 2 ÷ 4 =  0 R 2
 1 ÷ 4 =  0 R 1
 0 ÷ 4 =  0 R 0
-1 ÷ 4 = -1 R 3
         ^------ We have to decrease now, because we already have 0 four times
              ^-- We have to restart the cycle at 3

At the same time, the real number division gives us:

-1 ÷ 4 = -0.25
          ^----- There is still a 0 in front of the .

That's why -1 // 4 gives -1 but int(-1/4) gives 0.

> Is there any motivation for the differences between the functions?

Well, they serve different purposes: // is part of an integer calculation with remainders and int() gives you the part in front of the . of a real number operation.

You decide what you want to calculate, then you decide which operator to use in Python to get the correct result.

Good question. Keep on learning.

Solution 2 - Python

I would say that your observation that those 2 operations should be intuitively similar is expected since on positive numbers they behave identically. But if you look at their origins (one comes from mathematics and the other from computer science) then it makes more sense their different behavior.

You can look behind there concepts:

  • Floor division aka the floor function applied to the math division
  • Type conversion/Type casting

==================================================================

I)Floor division aka the floor function applied to the math division

The floor function is a very well established concept in mathematics.

From mathworld.wolfram: > The floor function |_ x_ |, also called the greatest integer function or integer value (Spanier and Oldham 1987), gives the largest integer less than or equal to x. The name and symbol for the floor function were coined by K. E. Iverson (Graham et al. 1994)

So floor division is nothing more than floor function applied to the math division. The behavior is very clear, "mathematically precise".

II)Type conversion/Type casting

From wikipedia:

> In computer science, type conversion, type casting, type > coercion and type juggling are different ways of changing an > expression from one data type to another.

In most of the programming languages, the casting form float to integer is applied by rounding rule (so there is a convention) :

  • Round toward 0 – directed rounding towards zero (also known as truncation)

Rounding rule according to IEEE 754.


So, in other words, the reason for the difference between integer division and float to int conversion in python is a mathematical one, here are some thoughts from Guido van Rossum (I guess I do not have to introduce him :D) (from the blog The history of Python, article "Why Python's Integer Division Floors")

> This disturbs some people, but there is a good mathematical reason. > The integer division operation (//) and its sibling, the modulo > operation (%), go together and satisfy a nice mathematical > relationship (all variables are integers): > > a/b = q with remainder r > > such that > > b*q + r = a and 0 <= r < b > > (assuming a and b are >= 0).

Solution 3 - Python

Based on the answer by @thomas-weller I also found myself a maybe novice explanation for the floor division result from his example of division with a remainder:

  • > 7 / 4 = 1 R 3 = 1 + 0,75 = 1.75
  • > -> R3 = 3/4 = 0.75
  • > -1 /4 = -1 R 3 = -1 + 0,75 (R3) = -0.25

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIsdjView Question on Stackoverflow
Solution 1 - PythonThomas WellerView Answer on Stackoverflow
Solution 2 - PythonkederracView Answer on Stackoverflow
Solution 3 - Pythons_horusView Answer on Stackoverflow