PTA A1065 A+B and C (64bit) (数据溢出)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fuckingone/article/details/82503361

题目看懂了。此字体颜色为不懂部分。

这道题根本没思路。体会到了 基础重要性

百度了数据溢出:

8+9=17

0 1000

0 1001 

1 0001(正溢)

(-9)+(-8)=(-17)

1 0111

1 1000

0 1111(负溢)

int溢出超出了int类型的最大值,如果是两个正数相加,溢出得到一个负数,或两个负数相加,溢出得到一个正数的情况,就叫溢出。负数是以补码形式存储的,因此-1就是二进制的全1。

long long 取值范围-2^63~ +(2^63-1)

分析:

题目中两个整数相加可能会溢出(正溢出或负溢出),直接进行大小判断会造成错误,计算机组成原理中指出,如果两个正数之和等于负数或者两个负数之和等于正数,就是溢出,对于溢出后的具体范围,进行如下分析。

①A+B>=2^63时,A+B>C成立,但A+B会因为超过long long正向最大值发生正溢出。由于题目中A、B最大值均为2^63-1,所以A+B最大值为2^63-2,因此用long long 存储正溢出后值的区间为[-2^63,-2] (由(2^64-2)%(2^64)=-2可得右边界)。所以当A>0,B>0,A+B<0时为正溢出,输出true。

②A+B<-2^63时,A+B<C成立,但A+B会因为超过long long负向最小值发生负溢出。由于题目中A、B最小值均为-2^63,所以A+B最小值为-2^64,因此用long long 存储负溢出后值的区间为[0,2^63] (由(-2^64)%(2^64)=0可得左边界)。所以当A<0,B<0,A+B>=0时为负溢出,输出false。

③没溢出情况下。>true。<=false。

注意:

①经测试,数据中A、B并没有取到2^63,题目中范围可能写错了,应该是[-2^63,2^63)才更符合数据,否则就要用带负数的大整数运算了(因为long long存储2^63时会自动变成-2^63,无法区分左右边界)。

②A+B必须存到long long型变量中才可以与C进行比较,不可以在if条件中直接相加与C比较,否则会造成后两组数据错误。

#include<cstdio>
using namespace std;
int main(){
  int t;
  long long a,b,c;
  scanf("%d",&t);
  for(int i=1;i<=t;i++){
    scanf("%lld %lld %lld",&a,&b,&c);
    long long res=a+b;
    bool flag;
    if(a>0&&b>0&&res<0)flag=true;  //正溢出
    else if(a<0&&b<0&&res>=0)flag=false;  //负溢出
    else if(res>c) flag=true;
    else flag=false;
    if(flag==true) printf("Case #%d: true\n",i);
    else printf("Case #%d: false\n",i);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/fuckingone/article/details/82503361