Q&A library Python

Why does -7 // 2 give -4 in Python?

Python Intermediate divisionintegersrounding

Short answer

Floor division rounds towards negative infinity, not towards zero, so a negative result rounds further down. Use int() on a true division if you want truncation towards zero instead.

The short version

// is floor division: it rounds down, towards negative infinity, not towards zero. So -7 // 2 is -4, not -3. If you want truncation towards zero (the behaviour many other languages have), divide normally and convert with int().

The behaviour

7 // 2      # 3
-7 // 2     # -4 , not -3
int(-7 / 2) # -3 , truncated towards zero

Positive numbers behave as everyone expects. Negative numbers are where the two conventions part company, and Python's choice surprises people coming from C, Java or SQL.

Why Python chose this

It keeps the relationship between // and % consistent, so that a == (a // b) * b + (a % b) always holds.

-7 % 2      # 1 , a positive remainder
(-7 // 2) * 2 + (-7 % 2)   # -4 * 2 + 1 = -7 , correct

Python's modulo always returns a result with the sign of the divisor, which is genuinely useful for cyclic arithmetic (clock faces, indexing into a circular buffer), and floor division is what makes that consistent. Languages that truncate towards zero produce negative remainders instead, which is more surprising in most practical uses.

Where this bites

Anywhere you compute an index, a bucket or a page number from a value that could be negative.

bucket = value // bucket_size     # a negative value lands one bucket lower than you might expect

If your data cannot be negative, none of this matters. If it can, decide explicitly which rounding you want, because the two differ by one for every negative value, and an off-by-one in a bucket assignment is exactly the sort of quiet error that reaches production.

Getting truncation towards zero

import math

math.trunc(-7 / 2)   # -3
int(-7 / 2)          # -3

Both cut off the fractional part, moving towards zero regardless of sign.

Note that math.floor does the same as //, rounding towards negative infinity, so it is not the alternative you want here.

In NumPy and pandas

The same rule applies to arrays and columns, so a column of negative values floor-divided will round down, not towards zero.

import numpy as np
np.array([-7]) // 2      # array([-4])

And np.trunc or casting to int gives the truncating behaviour if that is what you need.

The practical advice

Use // when you genuinely want the floor, which is most of the time for non-negative data and for cyclic arithmetic. When negatives are possible and the direction of rounding matters, write the rounding you mean explicitly (math.floor, math.trunc, round) rather than relying on an operator whose convention a reader may not share. Being explicit costs nothing and removes an easy source of off-by-one errors.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project