csapp笔记——2.3节整数运算

目录

无符号加法

补码加法

补码的非

无符号乘法

补码乘法

乘以常数

除以2的幂


无符号加法

对于0\leqslant x,y< 2^w的整数x,y,定义x+_{w}^{u}y表示将x与y的和截为w位

x+_{w}^{u}y=\left\{\begin{matrix} x+y, x+y<2^w \\ x+y-2^w ,2^w\leqslant x+y<2^{w+1} \end{matrix}\right.

由此推得检测无符号加法是否溢出得方法是判断结果是否比x,y中的任何一个小。

无符号数的逆元定义为使得x +_{w}^{u} y =0的y,若x为0则y为0,否则,y为2^w-x

补码加法

对于-2^{w-1}\leqslant x,y<2^{w-1}的整数x,y,定义x+_{w}^{t}y表示将x与y的和截为w位,这里指出,对于某个确定的位级表示,无论将它视作无符号数进行无符号数的截断加法,还是将它视作补码进行补码截断加法,所得到的最终位级表示是相同的。

 检测溢出

这里注意,模数加法形成阿贝尔群,也就是补码加法和无符号数加法满足交换律,那么不管是否存在溢出,(x+y)-x总会等于y。

补码的非

对于一个给定的位级表示,无论把他视为补码还是无符号数,其非的位级表示都是相同的。

在C语言中对于任意整数x,~x+1就是它的非

可以这么理解:

~x+x=[1...1],所以~x+x+1=[0...0]。

由此还可推得对于任意一个非零位级表示(只要x非零,必有一位是1)[x_{w-1},...,x_{k},1,0,...,0](这里的1表示从右往左数第一个1),对1左边的所有位取反就能得到其非。

无符号乘法

补码乘法

先给出一个结论,对于给定的两个位级表示,将其视作无符号数相乘或者补码相乘,截断后的最终结果是相同的。

所以对于补码乘法,可先将其视作无符号数相乘,得到相乘结果后再截断,将截断后的位级表示作为补码解释。

int32_t tmult_ok(int32_t x, int32_t y)
{
	int32_t p = x * y;
	return !x || p / x == y;
}

可用这段代码检测32位整数相乘是否溢出。

乘以常数

乘法指令的速度比其他整数运算要慢,编译器往往会尝试用移位和加减法的组合来代替乘以常数的乘法。

对于补码和无符号数来说,左移k位都代表乘2^k,对于一般的常数,编译器会将其分解为若干个2的次幂相加或者两个二的次幂相减,实际应用时可能既有相加又有相减,具体如下:

对于一个正数来说,[(0...0)(1...1)(0...0)(0...0)(1...1)...(1...1)]是他的位级表示,可能会有若干段连续的1,对于某一段连续的1来说,假设该段最高位是从整体最低位往左数第n个,最低位是从整体最低位往左数第k个,有两种方式表示

第一种

2^{n-1} + ... + 2^{k-1}

第二种

2^{n} - 2^{k-1}

对这一段就可以使用左移

除以2的幂

大多数机器上,除法比乘法更慢。但除法并不能像乘法一样分解为加减法,只能对常数为2的次幂的情况进行移位。

对于无符号数和补码的整数除法,我们希望会得到,一个向0取整的结果,对无符号数和大于零的补码来说,向右移k位相当于除以2^k,结果恰好是我们期望的向0取整。

对于小于零的补码,如此操作依然会得到向下取整的结果,这就不符合我们的预期。因此需要做出调整。

整数除法有如下特性

\left \lfloor x/y \right \rfloor = \left \lceil (x-1+y) / y\right \rceil

我们希望负数除法时能向0取整,也就是向上取整。

因此对于负数补码,只需计算\left \lceil (x-1+y) / y\right \rceil,当y为2的次幂时,计算(x + (1<<k)-1 )>>k即可。

附上例子,该函数可实现32位整数除以16

int div16(int32_t x)
{
	int tmp = (x >> 31) & 0xf;
	return (x + tmp) >> 4;
}

对于正数x,tmp为0,对于负数x,x>>31后得到的位级表示为全1,与0xf相与可得到低四位的值,也就是15.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值