【问题标题】:Integer Overflow w/ Multiplication in C整数溢出与 C 中的乘法
【发布时间】:2019-01-23 01:30:41
【问题描述】:

我最近一直在搞乱 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)会被我的条件捕获。

所以我所拥有的绝对行不通。有什么好的方法可以解决这个问题?

【问题讨论】:

标签: c integer overflow multiplication


【解决方案1】:

a*b &gt; INT_MAXa*b &lt; INT_MIN 时整数溢出。

这导致不等式:

如果b &gt; 0a &gt; INT_MAX/ba &lt; INT_MIN/b
如果b &lt; 0a &lt; INT_MAX/ba &gt; 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 &gt; 0b &gt; 0a &gt; INT_MAX/b
如果a &gt; 0b &lt; 0b &lt; INT_MIN/a
如果a &lt; 0b &gt; 0a &lt; INT_MIN/b
如果a &lt; 0b &lt; 0b &lt; 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;
}

【讨论】:

  • 在上一个版本中,您的意思可能是 long long 而不是 long。在大多数现代计算机中,long 的大小与 int 相同。也可以使用双精度。
  • @AlainMerigot 至少在我的机器上(带有 gcc 的 x86_64 linux)int32 位,long64 位,但这当然可能会有所不同。即使long long 也不能保证比int 宽,但我将其添加为可能性。是的,但我不喜欢用浮点数学解决int 问题的想法,因为在某些情况下这是一个坏主意(例如货币)。
猜你喜欢
  • 2020-06-12
  • 2015-03-30
  • 2012-01-21
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多