无符号加法
- 当有两个非负整数x,y,满足0<=x,y<2w。每个数都能表示为w位无符号数字。那么便有0<=x+y<=2w+1-2。若和为w+1位的数,让其再加上另一个数时,结果可能需要w+2个位。
因此,要完整表示算术运算的结果时,不能对结果的字长有限制。 - 无符号数的加法
而若要限定结果的字长,便可将x+y的结果截断为w位。例如
x=9=[1001] y=12=[1100]
x+y=21=[10101]
此时将结果截断为4位得到x+y=[0101]=5
此时也称x+y发生了溢出
- 算术运算的溢出,是指完整的整数结果不能放到数据类型的字长限制中去。
- 检测无符号数加法中的溢出
int uadd_ok(unsigned x,unsigned y){
int add=x+y;
if(add<x||add<y){
return 0;
}else{
return 1;
}
}
补码加法
-补码加法有着与无符号数加法相同的位级表示。
因此有
- 补码加法存在正溢出和负溢出两种溢出情况
-判断两补码数的加和是否溢出
int tadd_ok(int x,int y){
int sum=x+y;
if(x>0&&y>0){
if (sum<=0)
{
return 0;
}else{
return 1;
}
}else if(x<0&&y<0){
if(sum>=0){
return 0;
}else{
return 1;
}
}else{
return 1;
}
}
补码的非
- 补码数与其的非相加结果为0
- 当x!=TMax时,x的非是-x
- 当x=TMax时,x的非是其本身
由于TMax=2w-1,故TMax+TMax=2w,发生了负溢出,故结果为0,满足第一点。
无符号乘法
- 由于两个w-1位的数字相乘,结果可能需要2w位来表示,因此无符号乘法被定义为产生w位的值,即取乘积中低w位的值作为结果。
补码乘法
- 补码数相乘的方式与无符号乘法类似
- 补码乘法与无符号数乘法在位级表示是完全一致的
- 补码乘法结果的溢出可以用如下代码判断
int tmult_ok(int x, int y)
{
int p = x * y;
return !x || p / x == y;//x为0时,!x为真,返回1
} //x不为0,y为0时,p/x==0==y,返回1
//x*y发生溢出时,其补码乘法的结果一定小于真实结果x*y,因此补码乘法的结果p/x一定小于x*y/x=y,返回0
//故该测试函数可靠
乘以常数
- 当一个无符号数乘以2的整数次幂时,乘法过程可以被简化
x为w位的无符号整数,则运算x2k的结果便是将x的每一位左移k位,即在x的位表示后加上了k个0 - 由于补码乘法和无符号乘法在位表示上的一致性,2的幂与补码数相乘时的简化方法与无符号数相似
除以2的幂
- 除以2的幂的无符号除法
当一个数x除以2k时,只需对x的位表示进行逻辑右移k位便可得到结果 - 补码数除以2的幂,向下舍入
补码数除以2的幂与无符号除法类似
若补码数为正,则在逻辑右移时在高位补0
若补码数为负,则在逻辑右移时在高位补1 - 向上舍入
在计算补码数x除以2的k次幂时,可以先将x加上一定的偏量
偏量为2k-1,之后再将和右移k位