计算机中数相加(相减)的溢出原因详细解释

这个问题可能困惑很多初学者,之前网上的解释也大都比较简单,我来整理一份全面详细的解答

1,首先你要明白,计算机中的符号数有三种表示方法,即原码反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理。同时,加法和减法也可以统一处理(这里可以参考点击打开链接,里面有解释补码怎么写)。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

2,明白了计算机中数是以补码形式存在后,我们举例分析,比如我int a,分配给a八位二进制,因为要留一位做符号位(正负号),所以a能表示的数的范围(补码的形式)(实际上正数补码是其本身,负数补码是在原码(也就是二进制表示其正数的基础上符号位不变取反加一)是-2^(8-1)~2^(8-1)-1),之所以负数比正数范围大一,是因为补码中的符号位即表示符号,也可以表示数值如1000,0000(补码)表示-128,这是指在表示端点值的时候符号位才有双重含义。

3,这里举个负数补码计算的例子,分配八位计算-5-4=-9,首先-4的补码,先算4的原码0000,0100,取反加一1111,1100,同理-5补码1111,1011两个补码相加得1,1111,0111这里注意最高位的1舍去,得1111,0110(-9的补码)减一取反得0000,1001即-9的原码9的二进制表达

4,有了上面的铺垫,下面讲关键,溢出。也就是我们遇到的两个正数相加得负数,我们称正溢出,两个负数相加得正数,我们称负溢出。举例,现在我分配4位二进制(实际上语言里面最小分配8位,int)。可知4位二进制表示数的范围是-8~7,我们计算3+5,3的补码是0011,5的补码是0101,两者相加得1000(补码,之前说过边界值符号位也可以当数值位),可知首位符号位为1即为负数正溢出,实际上5+3=8>7而5+2即0101+0010=0111结果为+7不溢出,我们再来计算-5-4,和上面不同的是这次只分配了四位,-4补码1100,-5补码1011,两者相加10111舍去首位1(只分配了四位,多余的进位直接舍去)得0111(补码)表示正数,可以得负溢出。而-4-5=-9<-8,而-5-3即1101+1011=01000得1000表示-8不溢出,事实-3-5=-8正好是四位表示的负数的边界,不溢出。

5,这里给一个实际例题

PAT A1065.A+B and C

给出三个整数范围是[-2^63,2^63),如果A+B>C输出true,否则输出false

#include <cstdio>
int main(){
	int T,tcase=1;
	scanf("%d",&T);
	while(T--){
		long long a,b,c;
		scanf("%lld%lld%lld",&a,&b,&c);
		long long res=a+b;//rest存放a+b的结果
		printf("\nres = %ld\n",res);
		bool flag;
		if(a>0&&b>0&&res<0) flag=true; //正溢出为true
		else if(a<0&&b<0&&res>=0) flag=false; //负溢出为false
		else if(res>c) flag=true;
		else flag=false;
		if(flag==true){
			printf("Case #%d: true\n",tcase++);
		}else{
			printf("Case #&d: false\n",tcase++);
		}
	}
	return 0;
}

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值