Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does C++ integer division work for limit and negative values?

I am facing some strange results with integer division in C++. I am trying to calculate this: -2147483648 / -1.

What I get is 3 different results in 3 different scenarios:

int foo(int numerator, int denominator) {
    int res = numerator / denominator; // produces SIGFPE, Arithmetic exception interrupt

    cout << res << endl;
}

int main() {
    int res = -2147483648 / -1;
    cout << res << endl;               // prints -2147483648
    cout << -2147483648 / -1 << endl;  // prints 2147483648
    foo(-2147483648, -1);
    return 0;
}

Why does the integer division operation produces different results in different situations?

like image 866
Kareem Ergawy Avatar asked Aug 04 '16 14:08

Kareem Ergawy


People also ask

What happens when you divide an integer in C?

Integer division yields an integer result. For example, the expression 7 / 4 evaluates to 1 and the expression 17 / 5 evaluates to 3. C provides the remainder operator, %, which yields the remainder after integer division.

How does division work in C?

In the C Programming Language, the div function divides numerator by denominator. Based on that division calculation, the div function returns a structure containing two members - quotient and remainder.

How does integer divide work?

The % (integer divide) operator divides two numbers and returns the integer part of the result. The result returned is defined to be that which would result from repeatedly subtracting the divisor from the dividend while the dividend is larger than the divisor.

Does integer division round up or down?

If the divisor and dividend have opposite signs then the result is zero or negative. If the division is inexact then the quotient is rounded towards zero. That is, up if it is negative, and down if it is positive.


2 Answers

The literal -2147483648 / -1 is calculated by your compiler as 2147483648 in a data type that is wide enough to hold that value.

When the literal is printed out directly, it prints the value correctly.

When the literal is stored in res, it is cast to an int. An int appears to be 32 bits wide on your system. The value 2147483648 cannot be represented as a 32 bit signed integer, so the cast causes an overflow. On your system, this overflow results in the value -2147483648 (likely it's using two's complement).

Finally, when trying to perform the division at runtime (in the foo function), the SIGFPE exception occurs due to the overflow (because the int datatype cannot represent the result).

Note that all of these three options rely on platform dependent behavior :

  • the fact that the compiler doesn't generate any errors (or other issues) when the literal calculation overflows and just uses a data type large enough to hold the result
  • the fact that the int overflow when storing the literal generates that specific value (and no other issues)
  • the fact that the SIGFPE exception is thrown when overflowing at runtime
like image 76
Sander De Dycker Avatar answered Sep 21 '22 07:09

Sander De Dycker


Your outcome might be INT_MAX+1, in other words it probably overflows. That is Undefined Behavior, and anything can happen. For instance, a compiler may reject the code outright.

(A system might have INT_MAX >= 2147483648, but then you would expect the same result for your 3 testcases)

like image 36
MSalters Avatar answered Sep 22 '22 07:09

MSalters