整数运算
这一章倒是没有什么太大的难点,两个整数计算后,根据位模式再转换为对应数值即可。只要把握住位模式不变,值可能会变就行。
对于w=4的数来说,[1011]即可以表示为无符号数11,也可以表示补码-5。整数运算之后,只要看最后的位的结果就行。
加法
无符号数加法
对于两个w位的数,它们相加之后,结果可能是w+1位。因此,我们在位上计算出结果之后,会直接截断第一位,然后把剩下的位转换成无符号数,即得到结果。
x + y < $2^w$,结果正常:x+y
$2w$ $\le$ x + y < $2{w+1}$,结果溢出:$x+y-2^w$
溢出之后,就是取位置的模。
/**
* @brief 判断无符号加法是否溢出
* 注:unsigned int的范围是0-4294967295
* 刚刚用21e来测,肯定不溢出。。
*/
int uadd_ok(unsigned x, unsigned y)
{
unsigned sum = x + y;
return sum >= x;
}
补码加法
同无符号加法,只是需要注意的是,补码能表示负数、0、正数,因此,它在运算的时候,有可能会正溢出或负溢出。
回忆一下补码的底层,它是首位表示负权重的值,其余位表示正值。
当两个正数的补码相加后,如果发生了溢出,就说明是在符号位进位了!也就是说原值减去了$2^w$,马上变得非常非常小,转到了负数区间。
当两个负数补码相加后,如果发生了溢出,就说明是两个符号位相加变为0,并且后面没有进位,那符号位就变成了0,也就是转为正数。也就是说在原值的基础上加了$2^w$,转到正数区间。
int tadd_ok(int x, int y)
{
int sum = x + y;
if (x >= 0 && y >= 0 && sum < 0)
{
return 0;
}
else if (x < 0 && y < 0 && sum >= 0)
{
return 0;
}
return 1;
}
补码的非
补充一个小知识点,求非有两种方式:
- 各位取反+1
- 最后一个1之前的所有元素取反
特别的,$-T_=T_$
乘除法
这块没有教具体怎么算,但是里面一堆公式推导,算出来的结果会怎样怎样。
其实也是同上,直接截断。
不过这里说,乘除法都比较耗时,有一种方式可以优化——位移。
比如要计算x*14,因为$14=23+22+2^1$,所以x*14 = (x<<3) + (x<<2) + (x<<1)
小结
这章主要是动手算算,了解一下思路。
不过那堆理论证明,待以后再来补充吧……