计算机中用位来表示整数,一种方式只能表示非负数,一种可以表示有符号数。
无符号数编码:
补码编码:
由上面的定义可以知道补码与无符号之间的对应关系(见下式),最高位为0时,补码与无符号表示是一样的,而最高位为1时,举个例子,补码表示的-1对应于无符号数的4294967295(这里指的是32位数) 。
在整数运算之前必须先了解 整数的扩展和截断
扩展分为零扩展和符号扩展,零扩展是简单的在表示的开头添加0,适用于无符号数的扩展。而符号扩展在表示中添加最高有效位值的副本,适用于补码的扩展。比如4位的1101扩展成8位,即11111101,很容易证明无符号位的扩展不改变其值。
截断简单的来讲就是丢弃较高的位,这里我们把截断跟下面提到的‘取模’(mod)当做一回事。举个补码数字的截断,11101111截断到4位数值,得到的结果是1111即-1(这里还需要将位表示转换为无符号数),这里截断到4位于mod(16)等价(如果个人理解有误,还请看官指出)。
PS:这里的mod与c/c++中的%有区别,c/c++中的除法是往0靠近,举个例子,-7%4=-3。
整数加法 两个数的w位补码之和与无符号之和有完全相同的位级表示!
无符号加法,由于两个数加起来可能会增加表示位的个数,这会使得字长膨胀,在一般的编程语言内,只支持固定精度的运算。当两个无符号数相加溢出时(两个w位加起来可能得到w+1位的值),规定丢弃最高位,等价于计算和模上2^w。
补码加法,补码加法稍微复杂点,补码加法计算方法就是先将两个数转化为无符号数,相加(使用无符号加法的规则)之后再转化回来。
其实我们平时在计算的时候只要用上面公式即可,不需要每次做计算都把整个过程走一遍,比如说先转化在相加取模在转化,啊,太烦了。
整数乘法 补码和无符号乘法运算的位级表示一样,终于知道为什么使用补码了吧,机器用同一种乘法指令来对乘法进行计算,对于加法也是一样
无符号乘法,固定的位的个数,所以直接对乘法结果取模,当实际计算两个32位长度的整数时,计算结果存放在两个寄存器中,最终的结果即其中一个寄存器的值(低32位)。
补码乘法,先得到两个数的乘积(就是补码表示的数的乘积,比如-1*7=-7),然后截断,再转化为有符号数。计算的式子如下
现在来分析为什么乘法运算的位级表示一样,即为什么无符号和补码乘积的低位是相同的。因为对于相同的两个位模式,其表示的无符号值的乘积与补码乘积取模之后的结果是一样的,用x撇,y撇表示无符号值,x,y表示补码值,则有
带2^w的都被丢弃掉了,所以低位时相同的。这个等式的意思就是无符号乘积值的位级表示进行一系列操作可以得到补码沉积值的位级表示,但是这一系列操作只与高位有关(大于等于w+1),而最后结果只与低位有关。