关于int类型超出数据范围的一点讨论

关于int类型超出数据范围的一点讨论

lc第150题,题目本身不难,使用堆栈去实现。但是实现的过程中会有int超出数据范围的错误: 以下是我的代码:

public:
    int evalRPN(vector<string>& tokens) {
        stack<int>s;    // ???????
        int n=tokens.size();
    
        for(int i=0;i<n;i++)
        {
          if(tokens[i]=="+"||tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){
             int temp1=s.top();
             s.pop();
             int temp2=s.top();
             s.pop();
        
             if(tokens[i]=="+"){
                 s.push((long long)temp1+temp2);
             }else if(tokens[i]=="*"){
                 s.push((long long)temp2*temp1);    //?????????
             }else if(tokens[i]=="/"){
                 s.push((long long)temp2/temp1);
             }else{
                 s.push((long long)temp2-temp1);
             }
             continue;
          }else{
              s.push(atoi(tokens[i].c_str()));
          }
        }
        return s.top();
    }
};

出现错误的原因是我定义了一个存放int数据类型的堆栈,当结果为2147483648时就会出错,因为超出了int类型的表示范围,这些大家应该也都清楚。 然后我把数据类型强转为long long(如上面的代码所示),最终顺利通过。

好了,介绍完毕,正当我要进行下一道题的时候,我突然被一个问题所困扰: 在这一步代码中 s.push((long long)temp2*temp1); 其中的(long long)temp2*temp1 肯定是一个long long数据类型,这一点大家应该没什么疑问,但是我定义的stack是一个int类型啊,把一个long long类型的数据 push到stack中居然还能顺利通过?!

基于此,我在vs中进行了测试并且查阅了一些资料,我的测试代码:

{
	stack<int>s;
	int a = 1073741824;
	s.push((long long)a*2);
	s.push((long long)a * 2 + 1);
	s.push((long long)a*2+2);
	cout<<s.top()<<endl;
	s.pop();
	cout <<s.top()<< endl;
	s.pop();
	cout<<s.top()<<endl;
}

我的意图是把一个long long 类型的数据push到int的stack中会怎样,结果如下: 也就是说,虽然2147483648没有超出long long的范围,但是超出了int的范围,所以对于stack.top(),得到的数据仍然是产出范围后失效的数字。

当int超出范围时,比如2147483648时,会得到-2147483648 当继续增大int数据时,得到的内容会在原来的基础上加1,比如2147483649,得到的就是-2147483647;2147483650,得到的就是-2147483646

好了,找到了问题的关键,那么回过头来再看这道题: 是不是就离了个大谱。

− 128 ∗ ( − 128 ) = 16384 16384 ∗ ( − 128 ) = − 2097152 − 2097152 ∗ ( − 128 ) = 268435456 268435456 ∗ 8 = 2147483648 此时超出范围, p u s h 到 s t a c k 中后再取出来应该已经变成了 − 2147483648 − 2147483648 ∗ ( − 1 ) = 2147483648 -128*(-128)=16384\16384*(-128)= -2097152\-2097152*(-128)=268435456\268435456*8=2147483648 此时超出范围,push到stack中后再取出来应该已经变成了-2147483648\-2147483648*(-1)=2147483648 −128∗(−128)=1638416384∗(−128)=−2097152−2097152∗(−128)=268435456268435456∗8=2147483648此时超出范围,push到stack中后再取出来应该已经变成了−2147483648−2147483648∗(−1)=2147483648 结果应该是2147483648才对!

所以呢,还是希望lc的工作人员们细心排查bug,不然会误导很多人呀。 如果我的分析有误,也还请大佬批评指正!!!

经验分享 程序员 微信小程序 职场和发展