无符号数加法便是两个数相加,如果超过最大值那么就截断超过的位数。截断超过的位数也就相当于mod2^n,因为这样做超过的位都会被模去变成0.

有符号数加法相对复杂。先是变成无符号数加法,加完 之后再按有符号数编码去理解,这样就会产生两种溢出,正溢出和负溢出。

首先,如果两个数一正一负,则不可能产生进位。

正溢出很好理解,最高一位为符号位,假如两个正数一加,超过了最大值,那么第2^w-1位就会变成1,这一位是符号位,因此这个数字便会变成负数。

如果是负溢出,因为两个数最高位一定为1,如果2^w-2位没有发生进位的话,那么就产生了溢出,此时最高位为0,变成正数

例如:10111111+10111111(-65)=01111110(126)

所以说如果是正数溢出,则需要-2^m,如果是负溢出,则需要加上2^m

判定是否发生溢出

s=a+b;
if((a>0==b>0)&&(a<0!=s<0))
{
cout<<"发生溢出"<<endl;
}
else
{
cout<<"没有发生溢出"<<endl;
}

a>0==b>0的意义是判断a和b的符号是否相同,相同为真.a<0!=s<0的含义是判断a和s的符号是否
乘法溢出相对简单粗暴,直接把高位全部截断,也就是对2^w取模,有符号数乘法是先不管符号位直接把后面的位相乘,然后再把符号位补上。但是如果只考虑当前n位的话补码乘法和原码乘法结果相同。

具体来说首先对n位的a按照符号位扩充到2n,然后使用 a * b(除去符号位) - a * b的符号位