/ is true division and always returns a float. // is floor division: it divides and rounds down to the next smaller integer. So -7 // 2 is -4, not -3, because the exact answer is -3.5 and "down" means toward negative infinity.
Examples
7 / 2 # 3.5 7 // 2 # 3 -7 / 2 # -3.5 -7 // 2 # -4 (floors toward negative infinity) int(-7 / 2) # -3 (int() truncates toward zero, a different thing)
Many people expect -7 // 2 to be -3, as in languages such as C or Java, where integer division truncates toward zero. Python floors instead.
The modulo operator follows the same rule
Python keeps this identity true for all integers: a == (a // b) * b + (a % b). So the sign of the remainder follows the divisor:
-7 % 2 # 1 because -7 = (-4) * 2 + 1 7 % -2 # -1 because 7 = (-4) * -2 + (-1)
In C or Java, -7 % 2 gives -1. The Python result is always between 0 and the divisor, which is convenient for wrapping around, such as index % length.
Why a data engineer cares
- Bucketing and partitioning by hash:
hash(key) % num_bucketsgives a valid bucket from 0 tonum_buckets - 1in Python even when the hash is negative. In Java or SQL engines that use truncating modulo, a negative hash can give a negative bucket number, which is a classic bug, and engines usually add anabsor a pmod function (pmodin Spark SQL) to avoid it. If you re-implement a partitioning function in Python and compare with a JVM system, they may disagree. - Date and time arithmetic:
divmod(seconds, 3600)for hours and remainder works for negative offsets in a predictable way. - Percentages and averages: use
/for ratios, not//, or you lose the fraction.
Related details
divmod(a, b) returns both the quotient and the remainder at once. For decimal and money calculations, use decimal.Decimal rather than floats, since floats cannot represent most decimal fractions exactly.
Short answer
/ gives a float, // floors, -7 // 2 == -4, and the remainder keeps the identity, so -7 % 2 == 1.