信息的表示和处理
整数运算
加法运算
两个无符号数unsigned char a = 255
和unsigned char b = 1
相加结果为0
原因:a+b超过了unsigned char 所能表示的最大值255
溢出:超出数据类型所能表示的最大值
无符号数加法(Unsigned Addition)
引入符号表示w位的无符号数加法: + w u +^{u}_{w} +wu u代表无符号数,w表示w位
对于x和y两个加数,存在约束 0 < x / y < 2 w 0<x/y<2^{w} 0<x/y<2w ,若x+y小于 2 w 2^{w} 2w,结果与实际情况一致,若 2 w < = x + y < 2 w + 1 2^{w}<=x+y<2^{w+1} 2w<=x+y<2w+1 ,产生溢出
二进制表示
为了保持w位不变,最高位的1会被丢弃,因此相当于减去 2 w 2^{w} 2w
C语言中溢出不会报错
检测无符号加法的溢出(Detecting Overflow of Unsigned Addition)
用程序判断,返回值为1表示正常,返回值为0表示出现溢出
其中
if(sum < x && sum < y) return 0;
else return 1;
可以改为return sum>=x
证明:当出现溢出时,得到的和小于任意一个数(x或y)
有符号数加法(Two’s Complement Addition)
引入符号表示w位的无符号数加法: + w t +^{t}_{w} +wt t是补码的首字母缩写,w表示w位
想要准确表示有符号数的加法需要w+1位,为了避免数据的扩展,最后结果截断w位表示
有符号数的加法分为:正溢出和负溢出
正溢出: 2 w − 1 < = x + y 2^{w-1}<=x+y 2w−1<=x+y ,此时结果会减去 2 w 2^{w} 2w
负溢出: x + y < − 2 w − 1 x+y<-2^{w-1} x+y<−2w−1 ,此时结果会加上 2 w 2^{w} 2w
正溢出(Postive Overflow)
代码示例:
二进制表示,最高位的1表示负权重
负溢出(Negative Overflow)
最高位为0表示正权重
检测有符号数是否发生溢出(Overflow)
- 若两数为正,结果为负代表出现了正溢出
- 若两数为负,结果为正代表出现了负溢出
减法运算
加法逆元(Additive Inverse)
对于x存在x’,使x+x’ = x+x’ =0,那么x’为x的加法逆元
那么减法运算 y − x y-x y−x = y + x ′ y+x' y+x′
无符号数的加法逆元
对于无符号数x,根据无符号数的加法可知,它的加法逆元是 2 w − x ′ 2^{w}-x' 2w−x′
无符号数的加法逆元如图所示
有符号数的加法逆元(Two’s-Complement Negation)
当x为最小值时,根据有符号数的加法可知,它的加法逆元是 − 2 w − 1 -2^{w-1} −2w−1,补码最小值的逆元就是本身
乘法运算
无符号数的乘法运算(Unsigned Multiplication)
2个w位无符号数x和y,乘积可能需要2w位来表示,在C语言中定义了无符号数的乘法是w位,因此运行结果会截取低w位
补码的乘法(Two’s-Complement Multiplication)
无论是无符号乘法,还是补码乘法,运算结果的位级表示都是一样的
但是补码乘法,需要把无符号数转换成补码(有符号数)
完整的位级表示不同但是阶段后的位级表示相同
Bit-Level Equivalence
根据之前的定义
对于相同的二进制,无符号数x’与有符号数x之间的关系如图所示
证得:无符号数和有符号数截断后得位级表示相同
Multiplying by Constants
乘法指令的执行会涉及多个时钟周期,所以很多C语言编译器试图用移位、加法以及减法来代替乘法的操作
乘以2的幂的情况
x ∗ 2 = 左移 1 位 x*2 = 左移1位 x∗2=左移1位
x ∗ 4 = 左移 2 位 x*4 = 左移2位 x∗4=左移2位
. . . . . . ...... ......
x ∗ 2 k = 左移 k 位 x*2^{k} = 左移k位 x∗2k=左移k位
证明如图所示
乘以任意常数
例如: x ∗ 14 x*14 x∗14,14=8+4+2,这样可以用2个移位操作和2个加法操作来代替
除法运算
除法可以用右移来代替
无符号数用逻辑右移,有符号数用算术右移
除不尽(Rounds Toward Zero)
在整数除法中,如果遇到除不尽的情况总是向零舍入
当x大于等于0,y大于0时,结果将向下舍入
当x小于0,y大于0时,结果将向上舍入
除以2的幂(Dividing by Powers of 2)
无符号数除以2的幂的情况
对无符号数x右移k位的操作如图所示
为了方便描述引入两个变量x1,x2。x1是w-k位的无符号数,x2是k位的无符号数
可观察到 x 1 < < k + x 2 = x x_{1}<<k + x_{2} = x x1<<k+x2=x
由于x2是k位所以 0 < = x 2 < 2 k 0<=x_{2}<2^{k} 0<=x2<2k
因此x除以2的k次方,取整结果就等于x1,这与x右移k位结果一致
有符号数除以2的幂(Dividing by Powers of 2)
当补码的最高位为0(正数)时,算术右移与除以2的k次方一致
当补码的最高位为1(负数)时,算术右移会导致舍入并不是向0的方向,所以需要加上一个偏置
偏置= [(1 << k位) -1]
但是并不能推广到任意常数!