C中带乘法的整数溢出

时间:2019-01-23 01:30:42

标签: c integer overflow multiplication

我最近一直在搞弄C语言,并提出了整数重载的概念。我正在尝试创建一个程序,该程序检测两个相乘的32位整数是否能够适合另一个32位整数。

我了解整数溢出的概念以及整数最终如何溢出,但是我仍然想弄清楚该程序的逻辑。这是我到目前为止的内容:

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;
}

如您所见,我的程序可以检测到某些情况下的溢出情况,但其他一些情况(例如-2 * 3和-2 * -3)会被我的情况捕获。

所以我拥有的绝对无法使用。有什么好的方法可以解决这个问题?

1 个答案:

答案 0 :(得分:2)

a*b > INT_MAXa*b < INT_MIN时,整数溢出。

这导致不等式:

如果b > 0a > INT_MAX/ba < INT_MIN/b
如果b < 0a < INT_MAX/ba > INT_MIN/b

因此,如果int溢出,则输出的条件是:

b>0 && (a>INT_MAX/b || a<INT_MIN/b) || b<0 && (a<INT_MAX/b || a>INT_MIN/b)

由于INT_MIN/b可能会自身溢出(b=-1时),因此应单独检查。

这是一个相当长的条件,应该拆分并放入一个函数中

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;
}

另一种方法是将不等式分为四个域而不是两个域:

如果a > 0b > 0a > INT_MAX/b
如果a > 0b < 0b < INT_MIN/a
如果a < 0b > 0a < INT_MIN/b
如果a < 0b < 0b < INT_MAX/a

导致无需处理特殊情况的函数:

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;
}

当然,如果您可以使用更大宽度的类型,则它的复杂程度将降低(不能保证longlong longint宽,但是在许多平台上,这是情况):

int ismultoverflow(int a, int b)
{
    long x=a, y=b;

    if(x*y > INT_MAX || x*y < INT_MIN)
    {
        return 1;
    }

    return 0;
}