In Python, what is a good way to round towards zero in integer division?

Question:

1/2

gives

0

as it should. However,

-1/2

gives

-1

, but I want it to round towards 0 (i.e. I want -1/2 to be 0), regardless of whether it’s positive or negative. What is the best way to do that?

Asked By: blacktrance

||

Answers:

Try this. Only works for numbers greater than -1

import math

x = .5
y = -.5

print math.floor(math.fabs(x))
>> 0

print math.floor(math.fabs(y))
>> 0
Answered By: Conor Patrick

Python’s default division of integers is return the floor (towards negative infinity) with no ability to change that. You can read the BDFL’s reason why.

To do ’round up’ division, you would use:

>>> a=1
>>> b=2
>>> (a+(-a%b))//b
1
>>> a,b=-1,2
>>> (a+(-a%b))//b
0

To do truncation towards zero, and maintain integer division, you use (a+(-a%b))//b if either a or b are negative and the default division if both are positive.

This will do integer division and always round towards zero:

>>> a=1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a=-1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a,b=-3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
-1
>>> a,b=3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
1

footnote

Interestingly enough, C99 declares that round towards zero is the default:

#include <stdio.h>
int main(int argc, const char * argv[])
{

    int a=-3;
    int b=2;
    printf("a=%d, b=%d, a/b=%dn",a,b,a/b);
    a=3;
    printf("a=%d, b=%d, a/b=%dn",a,b,a/b);
    return 0;
}

Prints:

a=-3, b=2, a/b=-1
a=3, b=2, a/b=1
Answered By: dawg

Do floating point division then convert to an int. No extra modules needed.

Python 3:

>>> int(-1 / 2)
0
>>> int(-3 / 2)
-1
>>> int(1 / 2)
0
>>> int(3 / 2)
1

Python 2:

>>> int(float(-1) / 2)
0
>>> int(float(-3) / 2)
-1
>>> int(float(1) / 2)
0
>>> int(float(3) / 2)
1
Answered By: Tim

Correct code to do this is, in my opinion, too obscure to write as a 1-liner. So I’d put it in a function, like:

def int0div(a, b):
    q = a // b
    if q < 0 and b*q != a:
        q += 1
    return q

Good features: it works for any size of int, doesn’t make any adjustment to the raw (a//b) result unless necessary, only does one division (% also does a division under the covers), and doesn’t create any integers larger than the inputs. Those may or may not matter in your application; they become more important (for speed) if you use “big” integers.

Answered By: Tim Peters

Throwing my hat in with a few alternate ideas:

Multiple the sign of the number [abs(x)/x] by the abs(x)/2

(abs(x)/x)*(abs(x)/2)

Perform the addition, but if the number is less than zero add one to shift it closer to 0.

x/2 + int(x<0)
Answered By: user764357

For what it’s worth, my own favourite solution is this one. Integer arithmetic only, a single division, and everything else linear time:

def integer_divide_towards_zero(a, b):
    return -(-a // b) if a < 0 else a // b

That assumes that b is positive, but in most of the applications I’ve seen that’s true. If you need to deal with negative b too, then the function becomes marginally more complicated:

def integer_divide_towards_zero(a, b):
    return -(-a // b) if (a < 0) ^ (b < 0) else a // b

Some sample outputs:

>>> integer_divide_towards_zero(11, 3)
3
>>> integer_divide_towards_zero(-11, 3)
-3
>>> integer_divide_towards_zero(6, 3)
2
>>> integer_divide_towards_zero(-6, 3)
-2
>>> integer_divide_towards_zero(11, -3)
-3
>>> integer_divide_towards_zero(-11, -3)
3
Answered By: Mark Dickinson

You can also use the Decimal module as part of the standard python libraries.

Specifically,
” The integer division operator // behaves analogously, returning the integer part of the true quotient (truncating towards zero) rather than its floor, so as to preserve the usual identity x == (x // y) * y + x % y:”

>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')

Also, have a look at Rounding Modes as they’ve got quite a few ways to view/round your information – Ceiling, down, floor, half-down, half-even, half-up, up and 05up rounding.

Decimal was written as a solution to the traditional problem of binary mathematics in a world expecting decimals solutions

Answered By: jjisnow

why reinvent the wheel, when there’s a perfectly good math.trunc() function?

import math
print(math.trunc(-3.5))
>>-3
print(math.trunc(3.5))
>>3
Answered By: jjisnow