Reputation:
I've recently been messing around with C and have come to the concept of integer overloading. I'm trying to create a program that detects whether or not two 32 bit integers multiplied by each other will be able to fit into another 32 bit integer.
I understand the concept of integer overflow and how integers end up overflowing, but I'm stuck with figuring out the logic for this program. Here's what I have so far:
int main() {
int min = INT_MIN;
int max = INT_MAX;
int num1, num2;
int x = num1 * num2;
printf("Please enter a number you would like to multiply: ");
scanf("%d", &num1);
printf("\nPlease enter a second number you would like to multiply: ");
scanf("%d", &num2);
if (num1 > max / num2){
printf("\nOverflow! - first case\n");
}
else if (num2 > max / num1){
printf("\nOverflow! - second case\n");
}
else if ((num1 > max - num2 && num2 > 0 ) ||
(num1 < max - num2 && num2 < 0)){
printf("\nOverflow! - third case\n");
}
else
printf("\nNot Overflow!\n");
return 0;
}
As you can see, my program can detect some cases for overflow, but several other cases like -2 * 3 and -2 * -3 will get caught by my conditions.
So what I have will absolutely not work. What are good ways to go about solving this?
Upvotes: 1
Views: 3404
Reputation: 2813
An integer overflows when a*b > INT_MAX
or when a*b < INT_MIN
.
This leads to the inequations:
If b > 0
: a > INT_MAX/b
or a < INT_MIN/b
If b < 0
: a < INT_MAX/b
or a > INT_MIN/b
So the condition which outputs if an int
overflows is:
b>0 && (a>INT_MAX/b || a<INT_MIN/b) || b<0 && (a<INT_MAX/b || a>INT_MIN/b)
Since here INT_MIN/b
could overflow itself (when b=-1
) this should be checked seperately.
This is a rather long condition and should maybe be splitted up and put into a function:
int ismultoverflow(int a, int b)
{
if(b > 0)
{
if(a>INT_MAX/b || a<INT_MIN/b)
{
return 1;
}
}
else if(b < 0)
{
if(b == -1)
{
return a==INT_MIN;
}
if(a<INT_MAX/b || a>INT_MIN/b)
{
return 1;
}
}
return 0;
}
Another approach would be to group the inequations into four domains rather than two:
If a > 0
and b > 0
: a > INT_MAX/b
If a > 0
and b < 0
: b < INT_MIN/a
If a < 0
and b > 0
: a < INT_MIN/b
If a < 0
and b < 0
: b < INT_MAX/a
which leads to a function where you do not have to handle a special case:
int ismultoverflow(int a, int b)
{
if(a>0 && b>0 && a>INT_MAX/b)
{
return 1;
}
if(a>0 && b<0 && b<INT_MIN/a)
{
return 1;
}
if(a<0 && b>0 && a<INT_MIN/b)
{
return 1;
}
if(a<0 && b<0 && b<INT_MAX/a)
{
return 1;
}
return 0;
}
Of course if you could use types with larger width it is way less complicated (it is not guaranteed that long
or long long
are wider than int
, but on many platforms this is the case):
int ismultoverflow(int a, int b)
{
long x=a, y=b;
if(x*y > INT_MAX || x*y < INT_MIN)
{
return 1;
}
return 0;
}
Upvotes: 3