C ++理解整数溢出

时间:2019-06-15 20:37:34

标签: c++

在解决了LeetCode的一些C ++问题之后,我遇到了Reverse Integer,并意识到我无法真正掌握如何处理整数溢出。

问题很简单,并且在于反转整数(例如123-> 321)。现在,困难的部分是遵守以下限制:

  

假设我们正在处理的环境只能存储32位有符号整数范围内的整数:[− 2 31 ,2 31 − 1]。出于这个问题的目的,假设您的函数在反向整数溢出时返回0

我所做的是:

int reverse(int x) {
   int temp = 0;
   while(x != 0){
       // pop
       int pop = x%10;
       x /= 10;

       if(temp < (INT_MIN - pop)/10 || temp > (INT_MAX - pop)/10){
          return 0;
       }
       else{
           // push
           temp = temp*10 + pop;
      }
   }

   return temp;
}

不幸的是,该代码不能防止溢出。我在做什么错了?

3 个答案:

答案 0 :(得分:6)

pop的符号是实现定义的(在C ++ 11之前),如果INT_MIN - pop为负,则将导致溢出。因此,让我们首先将问题简化为正整数:

if (x == INT_MIN)    // INT_MIN cannot be inverted, handle it separately
    return 0;
const int sign = (x < 0) ? -1 : 1;
x *= sign;

溢出条件是:

10 * temp + pop > INT_MAX

经过简单的数学运算,我们得到:

temp > (INT_MAX - pop) / 10

此处pop始终为非负数,因此INT_MAX - pop不会溢出。最终结果是sign * temp。因为temp为正,所以-temp不会溢出(如果temp为负,则可能会溢出)。

答案 1 :(得分:0)

看来问题出在逻辑上。由于temp已初始化为0,因此pop无需输入条件。因此,只需编写if(temp < (INT_MIN)/10 || temp > (INT_MAX)/10)

最终代码如下,

int reverse(int x) {
   int temp = 0;
   while(x != 0){
       // pop
       int pop = x%10;
       x /= 10;

       if(temp < (INT_MIN)/10 || temp > (INT_MAX)/10){
          return 0;
       }
       else{
           // push
           temp = temp*10 + pop;
      }
   }

   return temp;
}

答案 2 :(得分:0)

我发现在光盘上显示二进制补码表示非常有帮助。

这里是 4 位整数的表示。最大值为 2^3-1 = 7。

对于 32 位整数,我们将看到最大值为 2^31-1

当我们将2^31-1加1时:顺时针移动一个,显然是-2^31,称为整数溢出

在您的情况下,当您反转 2^31 时会发生溢出,当您反转需要获得 2^31,但它不存在并且您需要返回 0(如问题说明中所问)

enter image description here

参考:https://courses.cs.washington.edu/courses/cse351/17wi/sections/03/CSE351-S03-2cfp_17wi.pdf