整数运算

这一章倒是没有什么太大的难点,两个整数计算后,根据位模式再转换为对应数值即可。只要把握住位模式不变,值可能会变就行。

对于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
  2. 最后一个1之前的所有元素取反

特别的,$-T_=T_$

乘除法

这块没有教具体怎么算,但是里面一堆公式推导,算出来的结果会怎样怎样。

其实也是同上,直接截断。

不过这里说,乘除法都比较耗时,有一种方式可以优化——位移。

比如要计算x*14,因为$14=23+22+2^1$,所以x*14 = (x<<3) + (x<<2) + (x<<1)

小结

这章主要是动手算算,了解一下思路。

不过那堆理论证明,待以后再来补充吧……